summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/accel_cal.c78
-rw-r--r--common/acpi.c435
-rw-r--r--common/adc.c87
l---------common/aes-gcm.c1
l---------common/aes.c1
-rw-r--r--common/als.c127
-rw-r--r--common/ap_hang_detect.c238
-rw-r--r--common/audio_codec.c157
-rw-r--r--common/audio_codec_dmic.c107
-rw-r--r--common/audio_codec_i2s_rx.c132
-rw-r--r--common/audio_codec_wov.c443
-rw-r--r--common/backlight_lid.c85
-rw-r--r--common/base32.c175
-rw-r--r--common/base_state.c68
-rw-r--r--common/battery.c812
-rw-r--r--common/battery_fuel_gauge.c283
-rw-r--r--common/blink.c30
-rw-r--r--common/bluetooth_le.c198
-rw-r--r--common/body_detection.c256
-rw-r--r--common/btle_hci_controller.c668
-rw-r--r--common/btle_ll.c861
-rw-r--r--common/build.mk6
-rw-r--r--common/button.c892
-rw-r--r--common/capsense.c86
-rw-r--r--common/cbi.c578
-rw-r--r--common/cbi_eeprom.c84
-rw-r--r--common/cbi_gpio.c72
-rw-r--r--common/cec.c137
-rw-r--r--common/charge_manager.c1625
-rw-r--r--common/charge_ramp.c54
-rw-r--r--common/charge_ramp_sw.c383
-rw-r--r--common/charge_state_v2.c3108
-rw-r--r--common/charger.c712
-rw-r--r--common/charger_profile_override.c201
-rw-r--r--common/clz.c44
-rw-r--r--common/crc.c129
-rw-r--r--common/crc8.c28
-rw-r--r--common/ctz.c27
l---------common/curve25519-generic.c1
l---------common/curve25519.c1
-rw-r--r--common/device_event.c146
-rw-r--r--common/device_state.c83
-rw-r--r--common/dps.c639
-rw-r--r--common/dptf.c204
-rw-r--r--common/ec.libsharedobjs.ld15
-rw-r--r--common/ec_ec_comm_client.c371
-rw-r--r--common/ec_ec_comm_server.c328
-rw-r--r--common/espi.c57
-rw-r--r--common/event_log.c186
-rw-r--r--common/extpower_common.c29
-rw-r--r--common/extpower_gpio.c60
-rw-r--r--common/fan.c622
-rw-r--r--common/flash.c1562
-rw-r--r--common/fmap.c260
-rw-r--r--common/fpsensor/OWNERS10
-rw-r--r--common/fpsensor/fpsensor.c887
-rw-r--r--common/fpsensor/fpsensor_crypto.c286
-rw-r--r--common/fpsensor/fpsensor_private.h19
-rw-r--r--common/fpsensor/fpsensor_state.c313
-rw-r--r--common/gesture.c335
-rw-r--r--common/gyro_cal.c630
-rw-r--r--common/gyro_still_det.c242
-rw-r--r--common/host_command_controller.c230
-rw-r--r--common/host_command_pd.c229
-rw-r--r--common/hotword_dsp_api.c35
-rw-r--r--common/i2c_bitbang.c363
-rw-r--r--common/i2c_hid_touchpad.c797
-rw-r--r--common/i2c_peripheral.c28
-rw-r--r--common/i2c_trace.c211
-rw-r--r--common/i2c_wedge.c341
-rw-r--r--common/inductive_charging.c107
-rw-r--r--common/init_rom.c69
-rw-r--r--common/ioexpander.c338
-rw-r--r--common/keyboard_8042.c1328
-rw-r--r--common/keyboard_8042_sharedlib.c181
-rw-r--r--common/keyboard_backlight.c161
-rw-r--r--common/keyboard_mkbp.c224
-rw-r--r--common/keyboard_scan.c1094
-rw-r--r--common/keyboard_test.c201
-rw-r--r--common/keyboard_vivaldi.c187
-rw-r--r--common/lb_common.c345
-rw-r--r--common/led_common.c89
-rw-r--r--common/led_onoff_states.c279
-rw-r--r--common/led_policy_std.c202
-rw-r--r--common/led_pwm.c311
-rw-r--r--common/lid_angle.c202
-rw-r--r--common/lightbar.c2068
-rw-r--r--common/mkbp_fifo.c241
-rw-r--r--common/mkbp_info.c147
-rw-r--r--common/mkbp_input_devices.c245
-rw-r--r--common/mock/README.md88
-rw-r--r--common/mock/battery_mock.c211
-rw-r--r--common/mock/build.mk23
-rw-r--r--common/mock/charge_manager_mock.c50
-rw-r--r--common/mock/dp_alt_mode_mock.c35
-rw-r--r--common/mock/fp_sensor_mock.c87
-rw-r--r--common/mock/fpsensor_detect_mock.c28
-rw-r--r--common/mock/fpsensor_state_mock.c34
-rw-r--r--common/mock/mkbp_events_mock.c26
-rw-r--r--common/mock/rollback_mock.c41
-rw-r--r--common/mock/tcpc_mock.c227
-rw-r--r--common/mock/tcpci_i2c_mock.c1004
-rw-r--r--common/mock/tcpm_mock.c72
-rw-r--r--common/mock/timer_mock.c22
-rw-r--r--common/mock/usb_mux_mock.c63
-rw-r--r--common/mock/usb_pd_dpm_mock.c72
-rw-r--r--common/mock/usb_pe_sm_mock.c120
-rw-r--r--common/mock/usb_prl_mock.c200
-rw-r--r--common/mock/usb_tc_sm_mock.c214
-rw-r--r--common/motion_orientation.c37
-rw-r--r--common/newton_fit.c186
-rw-r--r--common/ocpc.c767
-rw-r--r--common/onewire.c147
-rw-r--r--common/online_calibration.c394
-rw-r--r--common/pd_log.c134
-rw-r--r--common/peci.c165
-rw-r--r--common/peripheral_charger.c740
-rw-r--r--common/port80.c214
-rw-r--r--common/power_button.c227
-rw-r--r--common/power_button_x86.c575
-rw-r--r--common/pstore_commands.c101
-rw-r--r--common/pwm.c180
-rw-r--r--common/pwm_kblight.c46
-rw-r--r--common/regulator.c99
-rw-r--r--common/rollback.c520
-rw-r--r--common/rollback_private.h33
-rw-r--r--common/rsa.c259
-rw-r--r--common/rtc.c68
-rw-r--r--common/rwsig.c336
l---------common/sha256.c1
-rw-r--r--common/shmalloc.c393
-rw-r--r--common/spi_commands.c71
-rw-r--r--common/spi_flash.c707
-rw-r--r--common/spi_flash_reg.c190
-rw-r--r--common/spi_nor.c1091
-rw-r--r--common/stillness_detector.c110
-rw-r--r--common/switch.c128
-rw-r--r--common/temp_sensor.c173
-rw-r--r--common/test_util.c226
-rw-r--r--common/thermal.c345
-rw-r--r--common/throttle_ap.c164
-rw-r--r--common/update_fw.c328
-rw-r--r--common/usb_charger.c136
-rw-r--r--common/usb_common.c1027
-rw-r--r--common/usb_console_stream.c238
-rw-r--r--common/usb_i2c.c196
-rw-r--r--common/usb_pd_alt_mode_dfp.c1543
-rw-r--r--common/usb_pd_alt_mode_ufp.c22
-rw-r--r--common/usb_pd_console_cmd.c224
-rw-r--r--common/usb_pd_dual_role.c473
-rw-r--r--common/usb_pd_host_cmd.c590
-rw-r--r--common/usb_pd_policy.c969
-rw-r--r--common/usb_pd_protocol.c5449
-rw-r--r--common/usb_pd_tcpc.c1468
-rw-r--r--common/usb_port_power_dumb.c160
-rw-r--r--common/usb_port_power_smart.c257
-rw-r--r--common/usb_update.c594
-rw-r--r--common/usbc/build.mk51
-rw-r--r--common/usbc/dp_alt_mode.c292
-rw-r--r--common/usbc/tbt_alt_mode.c579
-rw-r--r--common/usbc/usb_mode.c311
-rw-r--r--common/usbc/usb_pd_console.c212
-rw-r--r--common/usbc/usb_pd_dp_ufp.c448
-rw-r--r--common/usbc/usb_pd_dpm.c704
-rw-r--r--common/usbc/usb_pd_host.c179
-rw-r--r--common/usbc/usb_pd_timer.c268
-rw-r--r--common/usbc/usb_pe_ctvpd_sm.c237
-rw-r--r--common/usbc/usb_pe_drp_sm.c7486
-rw-r--r--common/usbc/usb_prl_sm.c2471
-rw-r--r--common/usbc/usb_retimer_fw_update.c189
-rw-r--r--common/usbc/usb_sm.c202
-rw-r--r--common/usbc/usb_tc_ctvpd_sm.c1716
-rw-r--r--common/usbc/usb_tc_drp_acc_trysrc_sm.c4160
-rw-r--r--common/usbc/usb_tc_vpd_sm.c430
-rw-r--r--common/usbc/usbc_pd_policy.c48
-rw-r--r--common/usbc/usbc_task.c182
-rw-r--r--common/usbc_intr_task.c213
-rw-r--r--common/usbc_ocp.c131
-rw-r--r--common/usbc_ppc.c307
-rw-r--r--common/vboot/common.c58
-rw-r--r--common/vboot/efs2.c352
-rw-r--r--common/vboot/vb21_lib.c108
-rw-r--r--common/vboot/vboot.c228
-rw-r--r--common/vboot_hash.c498
-rw-r--r--common/virtual_battery.c359
-rw-r--r--common/vstore.c127
-rw-r--r--common/webusb_desc.c46
-rw-r--r--common/wireless.c169
188 files changed, 0 insertions, 78826 deletions
diff --git a/common/accel_cal.c b/common/accel_cal.c
deleted file mode 100644
index 533a14fbc4..0000000000
--- a/common/accel_cal.c
+++ /dev/null
@@ -1,78 +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.
- */
-
-#include "common.h"
-#include "console.h"
-#include "accel_cal.h"
-
-#define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ##args)
-
-#define TEMP_RANGE (CONFIG_ACCEL_CAL_MAX_TEMP - CONFIG_ACCEL_CAL_MIN_TEMP)
-
-void accel_cal_reset(struct accel_cal *cal)
-{
- int i;
-
- for (i = 0; i < cal->num_temp_windows; ++i) {
- kasa_reset(&(cal->algos[i].kasa_fit));
- newton_fit_reset(&(cal->algos[i].newton_fit));
- }
-}
-
-static inline int compute_temp_gate(const struct accel_cal *cal, fp_t temp)
-{
- int gate = (int) fp_div(fp_mul(temp - CONFIG_ACCEL_CAL_MIN_TEMP,
- INT_TO_FP(cal->num_temp_windows)),
- TEMP_RANGE);
-
- return gate < cal->num_temp_windows
- ? gate : (cal->num_temp_windows - 1);
-}
-
-test_mockable bool accel_cal_accumulate(
- struct accel_cal *cal, uint32_t timestamp, fp_t x, fp_t y, fp_t z,
- fp_t temp)
-{
- struct accel_cal_algo *algo;
-
- /* Test that we're within the temperature range. */
- if (temp >= CONFIG_ACCEL_CAL_MAX_TEMP ||
- temp <= CONFIG_ACCEL_CAL_MIN_TEMP)
- return false;
-
- /* Test that we have a still sample. */
- if (!still_det_update(&cal->still_det, timestamp, x, y, z))
- return false;
-
- /* We have a still sample, update x, y, and z to the mean. */
- x = cal->still_det.mean_x;
- y = cal->still_det.mean_y;
- z = cal->still_det.mean_z;
-
- /* Compute the temp gate. */
- algo = &cal->algos[compute_temp_gate(cal, temp)];
-
- kasa_accumulate(&algo->kasa_fit, x, y, z);
- if (newton_fit_accumulate(&algo->newton_fit, x, y, z)) {
- fp_t radius;
-
- kasa_compute(&algo->kasa_fit, cal->bias, &radius);
- if (ABS(radius - FLOAT_TO_FP(1.0f)) <
- CONFIG_ACCEL_CAL_KASA_RADIUS_THRES)
- goto accel_cal_accumulate_success;
-
- newton_fit_compute(&algo->newton_fit, cal->bias, &radius);
- if (ABS(radius - FLOAT_TO_FP(1.0f)) <
- CONFIG_ACCEL_CAL_NEWTON_RADIUS_THRES)
- goto accel_cal_accumulate_success;
- }
-
- return false;
-
-accel_cal_accumulate_success:
- accel_cal_reset(cal);
-
- return true;
-}
diff --git a/common/acpi.c b/common/acpi.c
deleted file mode 100644
index 941a8b2e56..0000000000
--- a/common/acpi.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/* Copyright 2013 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.
- */
-
-#include "acpi.h"
-#include "battery.h"
-#include "common.h"
-#include "console.h"
-#include "dptf.h"
-#include "ec_commands.h"
-#include "fan.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "keyboard_backlight.h"
-#include "lpc.h"
-#include "pwm.h"
-#include "timer.h"
-#include "tablet_mode.h"
-#include "usb_charge.h"
-#include "usb_common.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_LPC, outstr)
-#define CPRINTF(format, args...) cprintf(CC_LPC, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args)
-
-/* Last received ACPI command */
-static uint8_t __bss_slow acpi_cmd;
-/* First byte of data after ACPI command */
-static uint8_t __bss_slow acpi_addr;
-/* Number of data writes after command */
-static int __bss_slow acpi_data_count;
-/* Test byte in ACPI memory space */
-static uint8_t __bss_slow acpi_mem_test;
-
-#ifdef CONFIG_DPTF
-static int __bss_slow dptf_temp_sensor_id; /* last sensor ID written */
-static int __bss_slow dptf_temp_threshold; /* last threshold written */
-
-/*
- * Current DPTF profile number.
- * This is by default initialized to 1 if multi-profile DPTF is not supported.
- * If multi-profile DPTF is supported, this is by default initialized to 2 under
- * the assumption that profile #2 corresponds to lower thresholds and is a safer
- * profile to use until board or some EC driver sets the appropriate profile for
- * device mode.
- */
-static int current_dptf_profile = DPTF_PROFILE_DEFAULT;
-
-#endif
-
-/*
- * Keep a read cache of four bytes when burst mode is enabled, which is the
- * size of the largest non-string memmap data type.
- */
-#define ACPI_READ_CACHE_SIZE 4
-
-/* Start address that indicates read cache is flushed. */
-#define ACPI_READ_CACHE_FLUSHED (EC_ACPI_MEM_MAPPED_BEGIN - 1)
-
-/* Calculate size of valid cache based upon end of memmap data. */
-#define ACPI_VALID_CACHE_SIZE(addr) (MIN( \
- EC_ACPI_MEM_MAPPED_SIZE + EC_ACPI_MEM_MAPPED_BEGIN - (addr), \
- ACPI_READ_CACHE_SIZE))
-
-/*
- * In burst mode, read the requested memmap data and the data immediately
- * following it into a cache. For future reads in burst mode, try to grab
- * data from the cache. This ensures the continuity of multi-byte reads,
- * which is important when dealing with data types > 8 bits.
- */
-static struct {
- int enabled;
- uint8_t start_addr;
- uint8_t data[ACPI_READ_CACHE_SIZE];
-} acpi_read_cache;
-
-/*
- * Deferred function to ensure that ACPI burst mode doesn't remain enabled
- * indefinitely.
- */
-static void acpi_disable_burst_deferred(void)
-{
- acpi_read_cache.enabled = 0;
- lpc_clear_acpi_status_mask(EC_LPC_STATUS_BURST_MODE);
- CPUTS("ACPI missed burst disable?");
-}
-DECLARE_DEFERRED(acpi_disable_burst_deferred);
-
-#ifdef CONFIG_DPTF
-
-static int acpi_dptf_is_profile_valid(int n)
-{
-#ifdef CONFIG_DPTF_MULTI_PROFILE
- if ((n < DPTF_PROFILE_VALID_FIRST) || (n > DPTF_PROFILE_VALID_LAST))
- return EC_ERROR_INVAL;
-#else
- if (n != DPTF_PROFILE_DEFAULT)
- return EC_ERROR_INVAL;
-#endif
-
- return EC_SUCCESS;
-}
-
-int acpi_dptf_set_profile_num(int n)
-{
- int ret = acpi_dptf_is_profile_valid(n);
-
- if (ret == EC_SUCCESS) {
- current_dptf_profile = n;
- if (IS_ENABLED(CONFIG_DPTF_MULTI_PROFILE) &&
- IS_ENABLED(CONFIG_HOSTCMD_EVENTS)) {
- /* Notify kernel to update DPTF profile */
- host_set_single_event(EC_HOST_EVENT_MODE_CHANGE);
- }
- }
- return ret;
-}
-
-int acpi_dptf_get_profile_num(void)
-{
- return current_dptf_profile;
-}
-
-#endif
-
-/* Read memmapped data, returns read data or 0xff on error. */
-static int acpi_read(uint8_t addr)
-{
- uint8_t *memmap_addr = (uint8_t *)(lpc_get_memmap_range() + addr -
- EC_ACPI_MEM_MAPPED_BEGIN);
-
- /* Check for out-of-range read. */
- if (addr < EC_ACPI_MEM_MAPPED_BEGIN ||
- addr >= EC_ACPI_MEM_MAPPED_BEGIN + EC_ACPI_MEM_MAPPED_SIZE) {
- CPRINTS("ACPI read 0x%02x (ignored)",
- acpi_addr);
- return 0xff;
- }
-
- /* Read from cache if enabled (burst mode). */
- if (acpi_read_cache.enabled) {
- /* Fetch to cache on miss. */
- if (acpi_read_cache.start_addr == ACPI_READ_CACHE_FLUSHED ||
- acpi_read_cache.start_addr > addr ||
- addr - acpi_read_cache.start_addr >=
- ACPI_READ_CACHE_SIZE) {
- memcpy(acpi_read_cache.data,
- memmap_addr,
- ACPI_VALID_CACHE_SIZE(addr));
- acpi_read_cache.start_addr = addr;
- }
- /* Return data from cache. */
- return acpi_read_cache.data[addr - acpi_read_cache.start_addr];
- } else {
- /* Read directly from memmap data. */
- return *memmap_addr;
- }
-}
-
-/*
- * This handles AP writes to the EC via the ACPI I/O port. There are only a few
- * ACPI commands (EC_CMD_ACPI_*), but they are all handled here.
- */
-int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr)
-{
- int data = 0;
- int retval = 0;
- int result = 0xff; /* value for bogus read */
-
- /* Read command/data; this clears the FRMH status bit. */
- if (is_cmd) {
- acpi_cmd = value;
- acpi_data_count = 0;
- } else {
- data = value;
- /*
- * The first data byte is the ACPI memory address for
- * read/write commands.
- */
- if (!acpi_data_count++)
- acpi_addr = data;
- }
-
- /* Process complete commands */
- if (acpi_cmd == EC_CMD_ACPI_READ && acpi_data_count == 1) {
- /* ACPI read cmd + addr */
- switch (acpi_addr) {
- case EC_ACPI_MEM_VERSION:
- result = EC_ACPI_MEM_VERSION_CURRENT;
- break;
- case EC_ACPI_MEM_TEST:
- result = acpi_mem_test;
- break;
- case EC_ACPI_MEM_TEST_COMPLIMENT:
- result = 0xff - acpi_mem_test;
- break;
-#ifdef CONFIG_KEYBOARD_BACKLIGHT
- case EC_ACPI_MEM_KEYBOARD_BACKLIGHT:
- result = kblight_get();
- break;
-#endif
-#ifdef CONFIG_FANS
- case EC_ACPI_MEM_FAN_DUTY:
- result = dptf_get_fan_duty_target();
- break;
-#endif
-#ifdef CONFIG_DPTF
- case EC_ACPI_MEM_TEMP_ID:
- result = dptf_query_next_sensor_event();
- break;
-#endif
-#ifdef CONFIG_CHARGER
- case EC_ACPI_MEM_CHARGING_LIMIT:
- result = dptf_get_charging_current_limit();
- if (result >= 0)
- result /= EC_ACPI_MEM_CHARGING_LIMIT_STEP_MA;
- else
- result = EC_ACPI_MEM_CHARGING_LIMIT_DISABLED;
- break;
-#endif
-
- case EC_ACPI_MEM_DEVICE_ORIENTATION:
- result = 0;
-
-#ifdef CONFIG_TABLET_MODE
- result = tablet_get_mode() << EC_ACPI_MEM_TBMD_SHIFT;
-#endif
-
-#ifdef CONFIG_DPTF
- result |= (acpi_dptf_get_profile_num() &
- EC_ACPI_MEM_DDPN_MASK)
- << EC_ACPI_MEM_DDPN_SHIFT;
-#endif
- break;
-
- case EC_ACPI_MEM_DEVICE_FEATURES0:
- case EC_ACPI_MEM_DEVICE_FEATURES1:
- case EC_ACPI_MEM_DEVICE_FEATURES2:
- case EC_ACPI_MEM_DEVICE_FEATURES3: {
- int off = acpi_addr - EC_ACPI_MEM_DEVICE_FEATURES0;
- uint32_t val = get_feature_flags0();
-
- /* Flush EC_FEATURE_LIMITED bit. Having it reset to 0
- * means that FEATURES[0-3] are supported in the first
- * place, and the other bits are valid.
- */
- val &= ~1;
-
- result = val >> (8 * off);
- break;
- }
- case EC_ACPI_MEM_DEVICE_FEATURES4:
- case EC_ACPI_MEM_DEVICE_FEATURES5:
- case EC_ACPI_MEM_DEVICE_FEATURES6:
- case EC_ACPI_MEM_DEVICE_FEATURES7: {
- int off = acpi_addr - EC_ACPI_MEM_DEVICE_FEATURES4;
- uint32_t val = get_feature_flags1();
-
- result = val >> (8 * off);
- break;
- }
-
-#ifdef CONFIG_USB_PORT_POWER_DUMB
- case EC_ACPI_MEM_USB_PORT_POWER: {
- int i;
- const int port_count = MIN(8, USB_PORT_COUNT);
-
- /*
- * Convert each USB port power GPIO signal to a bit
- * field with max size 8 bits. USB port ID (index) 0 is
- * the least significant bit.
- */
- result = 0;
- for (i = 0; i < port_count; ++i) {
- if (gpio_get_level(usb_port_enable[i]) != 0)
- result |= 1 << i;
- }
- break;
- }
-#endif
-#ifdef CONFIG_USBC_RETIMER_FW_UPDATE
- case EC_ACPI_MEM_USB_RETIMER_FW_UPDATE:
- result = usb_retimer_fw_update_get_result();
- break;
-#endif
- default:
- result = acpi_read(acpi_addr);
- break;
- }
-
- /* Send the result byte */
- *resultptr = result;
- retval = 1;
-
- } else if (acpi_cmd == EC_CMD_ACPI_WRITE && acpi_data_count == 2) {
- /* ACPI write cmd + addr + data */
- switch (acpi_addr) {
- case EC_ACPI_MEM_TEST:
- acpi_mem_test = data;
- break;
-#ifdef CONFIG_BATTERY_V2
- case EC_ACPI_MEM_BATTERY_INDEX:
- CPRINTS("ACPI battery %d", data);
- battery_memmap_set_index(data);
- break;
-#endif
-#ifdef CONFIG_KEYBOARD_BACKLIGHT
- case EC_ACPI_MEM_KEYBOARD_BACKLIGHT:
- /*
- * Debug output with CR not newline, because the host
- * does a lot of keyboard backlights and it scrolls the
- * debug console.
- */
- CPRINTF("\r[%pT ACPI kblight %d]",
- PRINTF_TIMESTAMP_NOW, data);
- kblight_set(data);
- kblight_enable(data > 0);
- break;
-#endif
-#ifdef CONFIG_FANS
- case EC_ACPI_MEM_FAN_DUTY:
- dptf_set_fan_duty_target(data);
- break;
-#endif
-#ifdef CONFIG_DPTF
- case EC_ACPI_MEM_TEMP_ID:
- dptf_temp_sensor_id = data;
- break;
- case EC_ACPI_MEM_TEMP_THRESHOLD:
- dptf_temp_threshold = data + EC_TEMP_SENSOR_OFFSET;
- break;
- case EC_ACPI_MEM_TEMP_COMMIT:
- {
- int idx = data & EC_ACPI_MEM_TEMP_COMMIT_SELECT_MASK;
- int enable = data & EC_ACPI_MEM_TEMP_COMMIT_ENABLE_MASK;
- dptf_set_temp_threshold(dptf_temp_sensor_id,
- dptf_temp_threshold,
- idx, enable);
- break;
- }
-#endif
-#ifdef CONFIG_CHARGER
- case EC_ACPI_MEM_CHARGING_LIMIT:
- if (data == EC_ACPI_MEM_CHARGING_LIMIT_DISABLED) {
- dptf_set_charging_current_limit(-1);
- } else {
- data *= EC_ACPI_MEM_CHARGING_LIMIT_STEP_MA;
- dptf_set_charging_current_limit(data);
- }
- break;
-#endif
-
-#ifdef CONFIG_USB_PORT_POWER_DUMB
- case EC_ACPI_MEM_USB_PORT_POWER: {
- int i;
- int mode_field = data;
- const int port_count = MIN(8, USB_PORT_COUNT);
-
- /*
- * Read the port power bit field (with max size 8 bits)
- * and set the charge mode of each USB port accordingly.
- * USB port ID 0 is the least significant bit.
- */
- for (i = 0; i < port_count; ++i) {
- int mode = USB_CHARGE_MODE_DISABLED;
-
- if (mode_field & 1)
- mode = USB_CHARGE_MODE_ENABLED;
-
- if (usb_charge_set_mode(i, mode,
- USB_ALLOW_SUSPEND_CHARGE)) {
- CPRINTS("ERROR: could not set charge "
- "mode of USB port p%d to %d",
- i, mode);
- }
- mode_field >>= 1;
- }
- break;
- }
-#endif
-#ifdef CONFIG_USBC_RETIMER_FW_UPDATE
- case EC_ACPI_MEM_USB_RETIMER_FW_UPDATE:
- usb_retimer_fw_update_process_op(
- EC_ACPI_MEM_USB_RETIMER_PORT(data),
- EC_ACPI_MEM_USB_RETIMER_OP(data));
- break;
-#endif
- default:
- CPRINTS("ACPI write 0x%02x = 0x%02x (ignored)",
- acpi_addr, data);
- break;
- }
- } else if (acpi_cmd == EC_CMD_ACPI_QUERY_EVENT && !acpi_data_count) {
- /* Clear and return the lowest host event */
- int evt_index = lpc_get_next_host_event();
- CPRINTS("ACPI query = %d", evt_index);
- *resultptr = evt_index;
- retval = 1;
- } else if (acpi_cmd == EC_CMD_ACPI_BURST_ENABLE && !acpi_data_count) {
- /*
- * TODO: The kernel only enables BURST when doing multi-byte
- * value reads over the ACPI port. We don't do such reads
- * when our memmap data can be accessed directly over LPC,
- * so on LM4, for example, this is dead code. We might want
- * to add a config to skip this code for certain chips.
- */
- acpi_read_cache.enabled = 1;
- acpi_read_cache.start_addr = ACPI_READ_CACHE_FLUSHED;
-
- /* Enter burst mode */
- lpc_set_acpi_status_mask(EC_LPC_STATUS_BURST_MODE);
-
- /*
- * Disable from deferred function in case burst mode is enabled
- * for an extremely long time (ex. kernel bug / crash).
- */
- hook_call_deferred(&acpi_disable_burst_deferred_data, 1*SECOND);
-
- /* ACPI 5.0-12.3.3: Burst ACK */
- *resultptr = 0x90;
- retval = 1;
- } else if (acpi_cmd == EC_CMD_ACPI_BURST_DISABLE && !acpi_data_count) {
- acpi_read_cache.enabled = 0;
-
- /* Leave burst mode */
- hook_call_deferred(&acpi_disable_burst_deferred_data, -1);
- lpc_clear_acpi_status_mask(EC_LPC_STATUS_BURST_MODE);
- }
-
- return retval;
-}
diff --git a/common/adc.c b/common/adc.c
deleted file mode 100644
index c9e3a36e57..0000000000
--- a/common/adc.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/* Copyright 2013 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.
- */
-
-/* ADC module for Chrome EC */
-
-#include "adc.h"
-#include "common.h"
-#include "console.h"
-#include "ec_commands.h"
-#include "host_command.h"
-#include "util.h"
-
-/* 'adc' console command is not supported in continuous mode */
-#ifndef CONFIG_ADC_PROFILE_FAST_CONTINUOUS
-static enum adc_channel find_adc_channel_by_name(const char *name)
-{
- const struct adc_t *ch = adc_channels;
- int i;
-
- if (!name || !*name)
- return ADC_CH_COUNT;
-
- for (i = 0; i < ADC_CH_COUNT; i++, ch++) {
- if (!strcasecmp(name, ch->name))
- return i;
- }
-
- return ADC_CH_COUNT;
-}
-
-static int print_one_adc(int channel)
-{
- int v;
-
- v = adc_read_channel(channel);
- if (v == ADC_READ_ERROR)
- return EC_ERROR_UNKNOWN;
- ccprintf(" %s = %d mV\n", adc_channels[channel].name, v);
- return EC_SUCCESS;
-}
-
-static int command_adc(int argc, char **argv)
-{
- int i, ret;
-
- /* If a channel is specified, read only that one */
- if (argc == 2) {
- i = find_adc_channel_by_name(argv[1]);
- if (i == ADC_CH_COUNT)
- return EC_ERROR_PARAM1;
- return print_one_adc(i);
- } else {
- /* Otherwise print them all */
- for (i = 0; i < ADC_CH_COUNT; ++i) {
- ret = print_one_adc(i);
- if (ret)
- return ret;
- }
- return EC_SUCCESS;
- }
-}
-DECLARE_CONSOLE_COMMAND(adc, command_adc,
- "[name]",
- "Print ADC channel(s)");
-
-static enum ec_status hc_adc_read(struct host_cmd_handler_args *args)
-{
- const struct ec_params_adc_read *params = args->params;
- struct ec_response_adc_read *resp = args->response;
- enum adc_channel ch = (enum adc_channel)params->adc_channel;
- int32_t adc_value;
-
- if (ch >= ADC_CH_COUNT)
- return EC_RES_INVALID_PARAM;
-
- adc_value = adc_read_channel(ch);
- if (adc_value == ADC_READ_ERROR)
- return EC_RES_ERROR;
-
- resp->adc_value = adc_value;
- args->response_size = sizeof(*resp);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_ADC_READ, hc_adc_read, EC_VER_MASK(0));
-#endif /* CONFIG_ADC_PROFILE_FAST_CONTINUOUS */
diff --git a/common/aes-gcm.c b/common/aes-gcm.c
deleted file mode 120000
index 3176d85ff8..0000000000
--- a/common/aes-gcm.c
+++ /dev/null
@@ -1 +0,0 @@
-../third_party/boringssl/common/aes-gcm.c \ No newline at end of file
diff --git a/common/aes.c b/common/aes.c
deleted file mode 120000
index ed10836943..0000000000
--- a/common/aes.c
+++ /dev/null
@@ -1 +0,0 @@
-../third_party/boringssl/common/aes.c \ No newline at end of file
diff --git a/common/als.c b/common/als.c
deleted file mode 100644
index 2e9c7ba96c..0000000000
--- a/common/als.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/* Copyright 2013 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.
- */
-
-/* This provides the interface for any Ambient Light Sensors that are connected
- * to the EC instead of the AP.
- */
-
-#include "als.h"
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "system.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-
-#define CPUTS(outstr) cputs(CC_ALS, outstr)
-#define CPRINTS(format, args...) cprints(CC_ALS, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_ALS, format, ## args)
-
-
-#define ALS_POLL_PERIOD SECOND
-
-static int task_timeout = -1;
-
-int als_read(enum als_id id, int *lux)
-{
- int af = als[id].attenuation_factor;
- return als[id].read(lux, af);
-}
-
-void als_task(void *u)
-{
- int i, val;
- uint16_t *mapped = (uint16_t *)host_get_memmap(EC_MEMMAP_ALS);
- uint16_t als_data;
-
- while (1) {
- task_wait_event(task_timeout);
-
- /* If task was disabled while waiting do not read from ALS */
- if (task_timeout < 0)
- continue;
-
- for (i = 0; i < EC_ALS_ENTRIES && i < ALS_COUNT; i++) {
- als_data = als_read(i, &val) == EC_SUCCESS ? val : 0;
- mapped[i] = als_data;
- }
- }
-}
-
-static void als_task_enable(void)
-{
- int fail_count = 0;
- int err;
- int i;
-
- for (i = 0; i < EC_ALS_ENTRIES && i < ALS_COUNT; i++) {
- err = als[i].init();
- if (err) {
- fail_count++;
- CPRINTF("%s ALS sensor failed to initialize, err=%d\n",
- als[i].name, err);
- }
- }
-
- /*
- * If all the ALS filed to initialize, disable the ALS task.
- */
- if (fail_count == ALS_COUNT)
- task_timeout = -1;
- else
- task_timeout = ALS_POLL_PERIOD;
-
- task_wake(TASK_ID_ALS);
-}
-
-static void als_task_disable(void)
-{
- task_timeout = -1;
-}
-
-static void als_task_init(void)
-{
- /*
- * Enable ALS task in S0 only and may need to re-enable
- * when sysjumped.
- */
- if (system_jumped_late() &&
- chipset_in_state(CHIPSET_STATE_ON))
- als_task_enable();
-}
-
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, als_task_enable, HOOK_PRIO_ALS_INIT);
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, als_task_disable, HOOK_PRIO_DEFAULT);
-DECLARE_HOOK(HOOK_INIT, als_task_init, HOOK_PRIO_ALS_INIT);
-
-/*****************************************************************************/
-/* Console commands */
-
-#ifdef CONFIG_CMD_ALS
-static int command_als(int argc, char **argv)
-{
- int i, rv, val;
-
- for (i = 0; i < ALS_COUNT; i++) {
- ccprintf("%s: ", als[i].name);
- rv = als_read(i, &val);
- switch (rv) {
- case EC_SUCCESS:
- ccprintf("%d lux\n", val);
- break;
- default:
- ccprintf("Error %d\n", rv);
- }
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(als, command_als,
- NULL,
- "Print ALS values");
-#endif
diff --git a/common/ap_hang_detect.c b/common/ap_hang_detect.c
deleted file mode 100644
index 0c9e7a186d..0000000000
--- a/common/ap_hang_detect.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/* Copyright 2013 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.
- */
-
-/* AP hang detect logic */
-
-#include "ap_hang_detect.h"
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "lid_switch.h"
-#include "power_button.h"
-#include "timer.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_CHIPSET, outstr)
-#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args)
-
-static struct ec_params_hang_detect hdparams;
-
-static int active; /* Is hang detect timer active / counting? */
-static int timeout_will_reboot; /* Will the deferred call reboot the AP? */
-
-/**
- * Handle the hang detect timer expiring.
- */
-static void hang_detect_deferred(void);
-DECLARE_DEFERRED(hang_detect_deferred);
-
-static void hang_detect_deferred(void)
-{
- /* If we're no longer active, nothing to do */
- if (!active)
- return;
-
- /* If we're rebooting the AP, stop hang detection */
- if (timeout_will_reboot) {
- CPRINTS("hang detect triggering warm reboot");
- host_set_single_event(EC_HOST_EVENT_HANG_REBOOT);
- chipset_reset(CHIPSET_RESET_HANG_REBOOT);
- active = 0;
- return;
- }
-
- /* Otherwise, we're starting with the host event */
- CPRINTS("hang detect sending host event");
- host_set_single_event(EC_HOST_EVENT_HANG_DETECT);
-
- /* If we're also rebooting, defer for the remaining delay */
- if (hdparams.warm_reboot_timeout_msec) {
- CPRINTS("hang detect continuing (for reboot)");
- timeout_will_reboot = 1;
- hook_call_deferred(&hang_detect_deferred_data,
- (hdparams.warm_reboot_timeout_msec -
- hdparams.host_event_timeout_msec) * MSEC);
- } else {
- /* Not rebooting, so go back to idle */
- active = 0;
- }
-}
-
-/**
- * Start the hang detect timers.
- */
-static void hang_detect_start(const char *why)
-{
- /* If already active, don't restart timer */
- if (active)
- return;
-
- if (hdparams.host_event_timeout_msec) {
- CPRINTS("hang detect started on %s (for event)", why);
- timeout_will_reboot = 0;
- active = 1;
- hook_call_deferred(&hang_detect_deferred_data,
- hdparams.host_event_timeout_msec * MSEC);
- } else if (hdparams.warm_reboot_timeout_msec) {
- CPRINTS("hang detect started on %s (for reboot)", why);
- timeout_will_reboot = 1;
- active = 1;
- hook_call_deferred(&hang_detect_deferred_data,
- hdparams.warm_reboot_timeout_msec * MSEC);
- }
-}
-
-/**
- * Stop the hang detect timers.
- */
-static void hang_detect_stop(const char *why)
-{
- if (active)
- CPRINTS("hang detect stopped on %s", why);
-
- active = 0;
-}
-
-void hang_detect_stop_on_host_command(void)
-{
- if (hdparams.flags & EC_HANG_STOP_ON_HOST_COMMAND)
- hang_detect_stop("host cmd");
-}
-
-/*****************************************************************************/
-/* Hooks */
-
-static void hang_detect_power_button(void)
-{
- if (power_button_is_pressed()) {
- if (hdparams.flags & EC_HANG_START_ON_POWER_PRESS)
- hang_detect_start("power button");
- } else {
- if (hdparams.flags & EC_HANG_STOP_ON_POWER_RELEASE)
- hang_detect_stop("power button");
- }
-}
-DECLARE_HOOK(HOOK_POWER_BUTTON_CHANGE, hang_detect_power_button,
- HOOK_PRIO_DEFAULT);
-
-static void hang_detect_lid(void)
-{
- if (lid_is_open()) {
- if (hdparams.flags & EC_HANG_START_ON_LID_OPEN)
- hang_detect_start("lid open");
- } else {
- if (hdparams.flags & EC_HANG_START_ON_LID_CLOSE)
- hang_detect_start("lid close");
- }
-}
-DECLARE_HOOK(HOOK_LID_CHANGE, hang_detect_lid, HOOK_PRIO_DEFAULT);
-
-static void hang_detect_resume(void)
-{
- if (hdparams.flags & EC_HANG_START_ON_RESUME)
- hang_detect_start("resume");
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, hang_detect_resume, HOOK_PRIO_DEFAULT);
-
-static void hang_detect_suspend(void)
-{
- if (hdparams.flags & EC_HANG_STOP_ON_SUSPEND)
- hang_detect_stop("suspend");
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, hang_detect_suspend, HOOK_PRIO_DEFAULT);
-
-static void hang_detect_shutdown(void)
-{
- /* Stop the timers */
- hang_detect_stop("shutdown");
-
- /* Disable hang detection; it must be enabled every boot */
- memset(&hdparams, 0, sizeof(hdparams));
-}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, hang_detect_shutdown, HOOK_PRIO_DEFAULT);
-
-/*****************************************************************************/
-/* Host command */
-
-static enum ec_status
-hang_detect_host_command(struct host_cmd_handler_args *args)
-{
- const struct ec_params_hang_detect *p = args->params;
-
- /* Handle stopping hang timer on request */
- if (p->flags & EC_HANG_STOP_NOW) {
- hang_detect_stop("ap request");
-
- /* Ignore the other params */
- return EC_RES_SUCCESS;
- }
-
- /* Handle starting hang timer on request */
- if (p->flags & EC_HANG_START_NOW) {
- hang_detect_start("ap request");
-
- /* Ignore the other params */
- return EC_RES_SUCCESS;
- }
-
- /* If hang detect transitioning to disabled, stop timers */
- if (hdparams.flags && !p->flags)
- hang_detect_stop("ap flags=0");
-
- /* Save new params */
- hdparams = *p;
- CPRINTS("hang detect flags=0x%x, event=%d ms, reboot=%d ms",
- hdparams.flags, hdparams.host_event_timeout_msec,
- hdparams.warm_reboot_timeout_msec);
-
- /*
- * If warm reboot timeout is shorter than host event timeout, ignore
- * the host event timeout because a warm reboot will win.
- */
- if (hdparams.warm_reboot_timeout_msec &&
- hdparams.warm_reboot_timeout_msec <=
- hdparams.host_event_timeout_msec)
- hdparams.host_event_timeout_msec = 0;
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_HANG_DETECT,
- hang_detect_host_command,
- EC_VER_MASK(0));
-
-/*****************************************************************************/
-/* Console command */
-
-static int command_hang_detect(int argc, char **argv)
-{
- ccprintf("flags: 0x%x\n", hdparams.flags);
-
- ccputs("event: ");
- if (hdparams.host_event_timeout_msec)
- ccprintf("%d ms\n", hdparams.host_event_timeout_msec);
- else
- ccputs("disabled\n");
-
- ccputs("reboot: ");
- if (hdparams.warm_reboot_timeout_msec)
- ccprintf("%d ms\n", hdparams.warm_reboot_timeout_msec);
- else
- ccputs("disabled\n");
-
- ccputs("status: ");
- if (active)
- ccprintf("active for %s\n",
- timeout_will_reboot ? "reboot" : "event");
- else
- ccputs("inactive\n");
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(hangdet, command_hang_detect,
- NULL,
- "Print hang detect state");
diff --git a/common/audio_codec.c b/common/audio_codec.c
deleted file mode 100644
index 3f7203ad15..0000000000
--- a/common/audio_codec.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright 2019 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.
- */
-
-#include "audio_codec.h"
-#include "console.h"
-#include "host_command.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_AUDIO_CODEC, format, ## args)
-
-static const uint32_t capabilities =
- 0
-#ifdef CONFIG_AUDIO_CODEC_CAP_WOV_AUDIO_SHM
- | BIT(EC_CODEC_CAP_WOV_AUDIO_SHM)
-#endif
-#ifdef CONFIG_AUDIO_CODEC_CAP_WOV_LANG_SHM
- | BIT(EC_CODEC_CAP_WOV_LANG_SHM)
-#endif
- ;
-
-static struct {
- uint8_t cap;
- uint8_t type;
- uintptr_t *addr;
- uint32_t len;
-} shms[EC_CODEC_SHM_ID_LAST];
-
-static enum ec_status get_capabilities(struct host_cmd_handler_args *args)
-{
- struct ec_response_ec_codec_get_capabilities *r = args->response;
-
- r->capabilities = capabilities;
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-
-static enum ec_status get_shm_addr(struct host_cmd_handler_args *args)
-{
- const struct ec_param_ec_codec *p = args->params;
- struct ec_response_ec_codec_get_shm_addr *r = args->response;
- const uint8_t shm_id = p->get_shm_addr_param.shm_id;
-
- if (shm_id >= EC_CODEC_SHM_ID_LAST)
- return EC_RES_INVALID_PARAM;
- if (!shms[shm_id].addr || !audio_codec_capable(shms[shm_id].cap))
- return EC_RES_INVALID_PARAM;
- if (!*shms[shm_id].addr &&
- shms[shm_id].type == EC_CODEC_SHM_TYPE_EC_RAM)
- return EC_RES_ERROR;
-
- r->len = shms[shm_id].len;
- r->type = shms[shm_id].type;
- r->phys_addr = *shms[shm_id].addr;
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-
-static enum ec_status set_shm_addr(struct host_cmd_handler_args *args)
-{
- const struct ec_param_ec_codec *p = args->params;
- const uint8_t shm_id = p->set_shm_addr_param.shm_id;
- uintptr_t ap_addr, ec_addr;
-
- if (shm_id >= EC_CODEC_SHM_ID_LAST)
- return EC_RES_INVALID_PARAM;
- if (!shms[shm_id].addr || !audio_codec_capable(shms[shm_id].cap))
- return EC_RES_INVALID_PARAM;
- if (p->set_shm_addr_param.len < shms[shm_id].len)
- return EC_RES_INVALID_PARAM;
- if (*shms[shm_id].addr)
- return EC_RES_BUSY;
-
- ap_addr = (uintptr_t)p->set_shm_addr_param.phys_addr;
- if (audio_codec_memmap_ap_to_ec(ap_addr, &ec_addr) != EC_SUCCESS)
- return EC_RES_ERROR;
- *shms[shm_id].addr = ec_addr;
-
- args->response_size = 0;
- return EC_RES_SUCCESS;
-}
-
-static enum ec_status (*sub_cmds[])(struct host_cmd_handler_args *) = {
- [EC_CODEC_GET_CAPABILITIES] = get_capabilities,
- [EC_CODEC_GET_SHM_ADDR] = get_shm_addr,
- [EC_CODEC_SET_SHM_ADDR] = set_shm_addr,
-};
-
-#ifdef DEBUG_AUDIO_CODEC
-static char *strcmd[] = {
- [EC_CODEC_GET_CAPABILITIES] = "EC_CODEC_GET_CAPABILITIES",
- [EC_CODEC_GET_SHM_ADDR] = "EC_CODEC_GET_SHM_ADDR",
- [EC_CODEC_SET_SHM_ADDR] = "EC_CODEC_SET_SHM_ADDR",
-};
-BUILD_ASSERT(ARRAY_SIZE(sub_cmds) == ARRAY_SIZE(strcmd));
-#endif
-
-static enum ec_status host_command(struct host_cmd_handler_args *args)
-{
- const struct ec_param_ec_codec *p = args->params;
-
-#ifdef DEBUG_AUDIO_CODEC
- CPRINTS("subcommand: %s", strcmd[p->cmd]);
-#endif
-
- if (p->cmd < EC_CODEC_SUBCMD_COUNT)
- return sub_cmds[p->cmd](args);
-
- return EC_RES_INVALID_PARAM;
-}
-DECLARE_HOST_COMMAND(EC_CMD_EC_CODEC, host_command, EC_VER_MASK(0));
-
-/*
- * Exported interfaces.
- */
-int audio_codec_capable(uint8_t cap)
-{
- return capabilities & BIT(cap);
-}
-
-int audio_codec_register_shm(uint8_t shm_id, uint8_t cap,
- uintptr_t *addr, uint32_t len, uint8_t type)
-{
- if (shm_id >= EC_CODEC_SHM_ID_LAST)
- return EC_ERROR_INVAL;
- if (cap >= EC_CODEC_CAP_LAST)
- return EC_ERROR_INVAL;
- if (shms[shm_id].addr || shms[shm_id].len)
- return EC_ERROR_BUSY;
-
- shms[shm_id].cap = cap;
- shms[shm_id].addr = addr;
- shms[shm_id].len = len;
- shms[shm_id].type = type;
-
- return EC_SUCCESS;
-}
-
-__attribute__((weak))
-int audio_codec_memmap_ap_to_ec(uintptr_t ap_addr, uintptr_t *ec_addr)
-{
- return EC_ERROR_UNIMPLEMENTED;
-}
-
-int16_t audio_codec_s16_scale_and_clip(int16_t orig, uint8_t scalar)
-{
- int32_t val;
-
- val = (int32_t)orig * (int32_t)scalar;
- val = MIN(val, (int32_t)INT16_MAX);
- val = MAX(val, (int32_t)INT16_MIN);
- return val;
-}
diff --git a/common/audio_codec_dmic.c b/common/audio_codec_dmic.c
deleted file mode 100644
index c4f0b07a46..0000000000
--- a/common/audio_codec_dmic.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2019 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.
- */
-
-#include "audio_codec.h"
-#include "console.h"
-#include "host_command.h"
-
-#define CPRINTS(format, args...) cprints(CC_AUDIO_CODEC, format, ## args)
-
-static enum ec_status dmic_get_max_gain(struct host_cmd_handler_args *args)
-{
- struct ec_response_ec_codec_dmic_get_max_gain *r = args->response;
-
- if (audio_codec_dmic_get_max_gain(&r->max_gain) != EC_SUCCESS)
- return EC_RES_ERROR;
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-
-static enum ec_status dmic_set_gain_idx(struct host_cmd_handler_args *args)
-{
- const struct ec_param_ec_codec_dmic *p = args->params;
-
- if (audio_codec_dmic_set_gain_idx(
- p->set_gain_idx_param.channel,
- p->set_gain_idx_param.gain) != EC_SUCCESS)
- return EC_RES_ERROR;
-
- return EC_RES_SUCCESS;
-}
-
-static enum ec_status dmic_get_gain_idx(struct host_cmd_handler_args *args)
-{
- const struct ec_param_ec_codec_dmic *p = args->params;
- struct ec_response_ec_codec_dmic_get_gain_idx *r = args->response;
-
- if (audio_codec_dmic_get_gain_idx(
- p->get_gain_idx_param.channel, &r->gain) != EC_SUCCESS)
- return EC_RES_ERROR;
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-
-static enum ec_status (*sub_cmds[])(struct host_cmd_handler_args *) = {
- [EC_CODEC_DMIC_GET_MAX_GAIN] = dmic_get_max_gain,
- [EC_CODEC_DMIC_SET_GAIN_IDX] = dmic_set_gain_idx,
- [EC_CODEC_DMIC_GET_GAIN_IDX] = dmic_get_gain_idx,
-};
-
-#ifdef DEBUG_AUDIO_CODEC
-static char *strcmd[] = {
- [EC_CODEC_DMIC_GET_MAX_GAIN] = "EC_CODEC_DMIC_GET_MAX_GAIN",
- [EC_CODEC_DMIC_SET_GAIN_IDX] = "EC_CODEC_DMIC_SET_GAIN_IDX",
- [EC_CODEC_DMIC_GET_GAIN_IDX] = "EC_CODEC_DMIC_GET_GAIN_IDX",
-};
-BUILD_ASSERT(ARRAY_SIZE(sub_cmds) == ARRAY_SIZE(strcmd));
-#endif
-
-static enum ec_status dmic_host_command(struct host_cmd_handler_args *args)
-{
- const struct ec_param_ec_codec_dmic *p = args->params;
-
-#ifdef DEBUG_AUDIO_CODEC
- CPRINTS("DMIC subcommand: %s", strcmd[p->cmd]);
-#endif
-
- if (p->cmd < EC_CODEC_DMIC_SUBCMD_COUNT)
- return sub_cmds[p->cmd](args);
-
- return EC_RES_INVALID_PARAM;
-}
-DECLARE_HOST_COMMAND(EC_CMD_EC_CODEC_DMIC, dmic_host_command, EC_VER_MASK(0));
-
-#ifdef CONFIG_AUDIO_CODEC_DMIC_SOFTWARE_GAIN
-static uint8_t channel_gains[EC_CODEC_DMIC_CHANNEL_COUNT];
-
-int audio_codec_dmic_get_max_gain(uint8_t *gain)
-{
- *gain = CONFIG_AUDIO_CODEC_DMIC_MAX_SOFTWARE_GAIN;
- return EC_SUCCESS;
-}
-
-int audio_codec_dmic_set_gain_idx(uint8_t channel, uint8_t gain)
-{
- if (channel >= ARRAY_SIZE(channel_gains))
- return EC_ERROR_INVAL;
- if (gain > CONFIG_AUDIO_CODEC_DMIC_MAX_SOFTWARE_GAIN)
- return EC_ERROR_INVAL;
-
- channel_gains[channel] = gain;
- return EC_SUCCESS;
-}
-
-int audio_codec_dmic_get_gain_idx(uint8_t channel, uint8_t *gain)
-{
- if (channel >= ARRAY_SIZE(channel_gains))
- return EC_ERROR_INVAL;
-
- *gain = channel_gains[channel];
- return EC_SUCCESS;
-}
-#endif
diff --git a/common/audio_codec_i2s_rx.c b/common/audio_codec_i2s_rx.c
deleted file mode 100644
index aeae19bdca..0000000000
--- a/common/audio_codec_i2s_rx.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2019 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.
- */
-
-#include "audio_codec.h"
-#include "console.h"
-#include "host_command.h"
-
-#define CPRINTS(format, args...) cprints(CC_AUDIO_CODEC, format, ## args)
-
-static uint8_t i2s_rx_enabled;
-
-static enum ec_status i2s_rx_enable(struct host_cmd_handler_args *args)
-{
- if (i2s_rx_enabled)
- return EC_RES_BUSY;
-
- if (audio_codec_i2s_rx_enable() != EC_SUCCESS)
- return EC_RES_ERROR;
-
- i2s_rx_enabled = 1;
-
- return EC_RES_SUCCESS;
-}
-
-static enum ec_status i2s_rx_disable(struct host_cmd_handler_args *args)
-{
- if (!i2s_rx_enabled)
- return EC_RES_BUSY;
-
- if (audio_codec_i2s_rx_disable() != EC_SUCCESS)
- return EC_RES_ERROR;
-
- i2s_rx_enabled = 0;
-
- return EC_RES_SUCCESS;
-}
-
-static enum ec_status
-i2s_rx_set_sample_depth(struct host_cmd_handler_args *args)
-{
- const struct ec_param_ec_codec_i2s_rx *p = args->params;
- const uint8_t depth = p->set_sample_depth_param.depth;
-
- if (i2s_rx_enabled)
- return EC_RES_BUSY;
- if (depth >= EC_CODEC_I2S_RX_SAMPLE_DEPTH_COUNT)
- return EC_RES_INVALID_PARAM;
-
- if (audio_codec_i2s_rx_set_sample_depth(depth) != EC_SUCCESS)
- return EC_RES_ERROR;
-
- return EC_RES_SUCCESS;
-}
-
-static enum ec_status i2s_rx_set_daifmt(struct host_cmd_handler_args *args)
-{
- const struct ec_param_ec_codec_i2s_rx *p = args->params;
- const uint8_t daifmt = p->set_daifmt_param.daifmt;
-
- if (i2s_rx_enabled)
- return EC_RES_BUSY;
- if (daifmt >= EC_CODEC_I2S_RX_DAIFMT_COUNT)
- return EC_RES_INVALID_PARAM;
-
- if (audio_codec_i2s_rx_set_daifmt(daifmt) != EC_SUCCESS)
- return EC_RES_ERROR;
-
- return EC_RES_SUCCESS;
-}
-
-static enum ec_status i2s_rx_set_bclk(struct host_cmd_handler_args *args)
-{
- const struct ec_param_ec_codec_i2s_rx *p = args->params;
-
- if (i2s_rx_enabled)
- return EC_RES_BUSY;
-
- if (audio_codec_i2s_rx_set_bclk(p->set_bclk_param.bclk) != EC_SUCCESS)
- return EC_RES_ERROR;
-
- return EC_RES_SUCCESS;
-}
-
-static enum ec_status i2s_rx_reset(struct host_cmd_handler_args *args)
-{
- if (audio_codec_i2s_rx_disable() != EC_SUCCESS)
- return EC_RES_ERROR;
-
- i2s_rx_enabled = 0;
-
- return EC_RES_SUCCESS;
-}
-
-static enum ec_status (*sub_cmds[])(struct host_cmd_handler_args *) = {
- [EC_CODEC_I2S_RX_ENABLE] = i2s_rx_enable,
- [EC_CODEC_I2S_RX_DISABLE] = i2s_rx_disable,
- [EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH] = i2s_rx_set_sample_depth,
- [EC_CODEC_I2S_RX_SET_DAIFMT] = i2s_rx_set_daifmt,
- [EC_CODEC_I2S_RX_SET_BCLK] = i2s_rx_set_bclk,
- [EC_CODEC_I2S_RX_RESET] = i2s_rx_reset,
-};
-
-#ifdef DEBUG_AUDIO_CODEC
-static char *strcmd[] = {
- [EC_CODEC_I2S_RX_ENABLE] = "EC_CODEC_I2S_RX_ENABLE",
- [EC_CODEC_I2S_RX_DISABLE] = "EC_CODEC_I2S_RX_DISABLE",
- [EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH] = "EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH",
- [EC_CODEC_I2S_RX_SET_DAIFMT] = "EC_CODEC_I2S_RX_SET_DAIFMT",
- [EC_CODEC_I2S_RX_SET_BCLK] = "EC_CODEC_I2S_RX_SET_BCLK",
- [EC_CODEC_I2S_RX_RESET] = "EC_CODEC_I2S_RESET",
-};
-BUILD_ASSERT(ARRAY_SIZE(sub_cmds) == ARRAY_SIZE(strcmd));
-#endif
-
-static enum ec_status i2s_rx_host_command(struct host_cmd_handler_args *args)
-{
- const struct ec_param_ec_codec_i2s_rx *p = args->params;
-
-#ifdef DEBUG_AUDIO_CODEC
- CPRINTS("I2S RX subcommand: %s", strcmd[p->cmd]);
-#endif
-
- if (p->cmd < EC_CODEC_I2S_RX_SUBCMD_COUNT)
- return sub_cmds[p->cmd](args);
-
- return EC_RES_INVALID_PARAM;
-}
-DECLARE_HOST_COMMAND(EC_CMD_EC_CODEC_I2S_RX,
- i2s_rx_host_command, EC_VER_MASK(0));
diff --git a/common/audio_codec_wov.c b/common/audio_codec_wov.c
deleted file mode 100644
index f84e45f342..0000000000
--- a/common/audio_codec_wov.c
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- * Copyright 2019 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.
- */
-
-#include "audio_codec.h"
-#include "console.h"
-#include "host_command.h"
-#include "hotword_dsp_api.h"
-#include "sha256.h"
-#include "system.h"
-#include "task.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_AUDIO_CODEC, format, ## args)
-
-/*
- * To shorten the variable names, or the following code is likely to greater
- * than 80 columns.
- */
-#define AUDIO_BUF_LEN CONFIG_AUDIO_CODEC_WOV_AUDIO_BUF_LEN
-#define LANG_BUF_LEN CONFIG_AUDIO_CODEC_WOV_LANG_BUF_LEN
-
-static uint8_t lang_hash[SHA256_DIGEST_SIZE];
-static uint32_t lang_len;
-
-/*
- * The variables below are shared between host command and WoV task. This lock
- * is designed to protect them.
- */
-static struct mutex lock;
-
-/*
- * wov_enabled is shared.
- *
- * host command task:
- * - is the only writer
- * - no need to lock if read
- */
-static uint8_t wov_enabled;
-
-/*
- * hotword_detected is shared.
- */
-static uint8_t hotword_detected;
-
-/*
- * audio_buf_rp and audio_buf_wp are shared.
- *
- * Note that: sample width is 16-bit.
- *
- * Typical ring-buffer implementation:
- * If audio_buf_rp == audio_buf_wp, empty.
- * If (audio_buf_wp + 2) % buf_len == audio_buf_rp, full.
- */
-static uint32_t audio_buf_rp, audio_buf_wp;
-
-static int is_buf_full(void)
-{
- return ((audio_buf_wp + 2) % AUDIO_BUF_LEN) == audio_buf_rp;
-}
-
-/* only used by host command */
-static uint8_t speech_lib_loaded;
-
-static int check_lang_buf(uint8_t *data, uint32_t len, const uint8_t *hash)
-{
- /*
- * Note: sizeof(struct sha256_ctx) = 200 bytes
- * should put into .bss, or stack is likely to overflow (~640 bytes)
- */
- static struct sha256_ctx ctx;
- uint8_t *digest;
- int i;
- uint8_t *p = (uint8_t *)audio_codec_wov_lang_buf_addr;
-
- SHA256_init(&ctx);
- SHA256_update(&ctx, data, len);
- digest = SHA256_final(&ctx);
-
-#ifdef DEBUG_AUDIO_CODEC
- CPRINTS("data=%08x len=%d", data, len);
- hexdump(digest, SHA256_DIGEST_SIZE);
-#endif
-
- if (memcmp(digest, hash, SHA256_DIGEST_SIZE) != 0)
- return EC_ERROR_UNKNOWN;
-
- for (i = len; i < LANG_BUF_LEN; ++i)
- if (p[i])
- return EC_ERROR_UNKNOWN;
-
- return EC_SUCCESS;
-}
-
-#ifdef CONFIG_AUDIO_CODEC_CAP_WOV_LANG_SHM
-static enum ec_status wov_set_lang_shm(struct host_cmd_handler_args *args)
-{
- const struct ec_param_ec_codec_wov *p = args->params;
- const struct ec_param_ec_codec_wov_set_lang_shm *pp =
- &p->set_lang_shm_param;
-
- if (pp->total_len > LANG_BUF_LEN)
- return EC_RES_INVALID_PARAM;
- if (wov_enabled)
- return EC_RES_BUSY;
-
- if (check_lang_buf((uint8_t *)audio_codec_wov_lang_buf_addr,
- pp->total_len, pp->hash) != EC_SUCCESS)
- return EC_RES_ERROR;
-
- memcpy(lang_hash, pp->hash, sizeof(lang_hash));
- lang_len = pp->total_len;
- speech_lib_loaded = 0;
-
- args->response_size = 0;
- return EC_RES_SUCCESS;
-}
-#else
-static enum ec_status wov_set_lang(struct host_cmd_handler_args *args)
-{
- const struct ec_param_ec_codec_wov *p = args->params;
- const struct ec_param_ec_codec_wov_set_lang *pp = &p->set_lang_param;
-
- if (pp->total_len > LANG_BUF_LEN)
- return EC_RES_INVALID_PARAM;
- if (pp->offset >= LANG_BUF_LEN)
- return EC_RES_INVALID_PARAM;
- if (pp->len > ARRAY_SIZE(pp->buf))
- return EC_RES_INVALID_PARAM;
- if (pp->offset + pp->len > pp->total_len)
- return EC_RES_INVALID_PARAM;
- if (wov_enabled)
- return EC_RES_BUSY;
-
- if (!pp->offset)
- memset((uint8_t *)audio_codec_wov_lang_buf_addr,
- 0, LANG_BUF_LEN);
-
- memcpy((uint8_t *)audio_codec_wov_lang_buf_addr + pp->offset,
- pp->buf, pp->len);
-
- if (pp->offset + pp->len == pp->total_len) {
- if (check_lang_buf((uint8_t *)audio_codec_wov_lang_buf_addr,
- pp->total_len, pp->hash) != EC_SUCCESS)
- return EC_RES_ERROR;
-
- memcpy(lang_hash, pp->hash, sizeof(lang_hash));
- lang_len = pp->total_len;
- speech_lib_loaded = 0;
- }
-
- args->response_size = 0;
- return EC_RES_SUCCESS;
-}
-#endif /* CONFIG_AUDIO_CODEC_CAP_WOV_LANG_SHM */
-
-static enum ec_status wov_get_lang(struct host_cmd_handler_args *args)
-{
- struct ec_response_ec_codec_wov_get_lang *r = args->response;
-
- memcpy(r->hash, lang_hash, sizeof(r->hash));
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-
-static enum ec_status wov_enable(struct host_cmd_handler_args *args)
-{
- if (wov_enabled)
- return EC_RES_BUSY;
-
- if (audio_codec_wov_enable() != EC_SUCCESS)
- return EC_RES_ERROR;
-
- if (!speech_lib_loaded) {
- if (!GoogleHotwordDspInit(
- (void *)audio_codec_wov_lang_buf_addr))
- return EC_RES_ERROR;
- speech_lib_loaded = 1;
- } else {
- GoogleHotwordDspReset();
- }
-
- mutex_lock(&lock);
- wov_enabled = 1;
- hotword_detected = 0;
- audio_buf_rp = audio_buf_wp = 0;
- mutex_unlock(&lock);
-
-#ifdef HAS_TASK_WOV
- task_wake(TASK_ID_WOV);
-#endif
-
- args->response_size = 0;
- return EC_RES_SUCCESS;
-}
-
-static enum ec_status wov_disable(struct host_cmd_handler_args *args)
-{
- if (!wov_enabled)
- return EC_RES_BUSY;
-
- if (audio_codec_wov_disable() != EC_SUCCESS)
- return EC_RES_ERROR;
-
- mutex_lock(&lock);
- wov_enabled = 0;
- hotword_detected = 0;
- audio_buf_rp = audio_buf_wp = 0;
- mutex_unlock(&lock);
-
- args->response_size = 0;
- return EC_RES_SUCCESS;
-}
-
-#ifdef CONFIG_AUDIO_CODEC_CAP_WOV_AUDIO_SHM
-static enum ec_status wov_read_audio_shm(struct host_cmd_handler_args *args)
-{
- struct ec_response_ec_codec_wov_read_audio_shm *r = args->response;
-
- if (!wov_enabled)
- return EC_RES_ACCESS_DENIED;
-
- mutex_lock(&lock);
- if (!hotword_detected) {
- mutex_unlock(&lock);
- return EC_RES_ACCESS_DENIED;
- }
-
- r->offset = audio_buf_rp;
- if (audio_buf_rp <= audio_buf_wp)
- r->len = audio_buf_wp - audio_buf_rp;
- else
- r->len = AUDIO_BUF_LEN - audio_buf_rp;
-
- audio_buf_rp += r->len;
- if (audio_buf_rp == AUDIO_BUF_LEN)
- audio_buf_rp = 0;
- mutex_unlock(&lock);
-
-#ifdef DEBUG_AUDIO_CODEC
- if (!r->len)
- CPRINTS("underrun detected");
-#endif
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-#else
-static enum ec_status wov_read_audio(struct host_cmd_handler_args *args)
-{
- struct ec_response_ec_codec_wov_read_audio *r = args->response;
- uint8_t *p;
-
- if (!wov_enabled)
- return EC_RES_ACCESS_DENIED;
-
- mutex_lock(&lock);
- if (!hotword_detected) {
- mutex_unlock(&lock);
- return EC_RES_ACCESS_DENIED;
- }
-
- if (audio_buf_rp <= audio_buf_wp)
- r->len = audio_buf_wp - audio_buf_rp;
- else
- r->len = AUDIO_BUF_LEN - audio_buf_rp;
- r->len = MIN(sizeof(r->buf), r->len);
-
- p = (uint8_t *)audio_codec_wov_audio_buf_addr + audio_buf_rp;
-
- audio_buf_rp += r->len;
- if (audio_buf_rp == AUDIO_BUF_LEN)
- audio_buf_rp = 0;
- mutex_unlock(&lock);
-
-#ifdef DEBUG_AUDIO_CODEC
- if (!r->len)
- CPRINTS("underrun detected");
-#endif
- /*
- * Note: it is possible to copy corrupted audio data if overrun
- * happened at the point. To keep it simple and align to SHM mode,
- * we ignore the case if overrun happened.
- */
- memcpy(r->buf, p, r->len);
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-#endif /* CONFIG_AUDIO_CODEC_CAP_WOV_AUDIO_SHM */
-
-static enum ec_status (*sub_cmds[])(struct host_cmd_handler_args *) = {
-#ifdef CONFIG_AUDIO_CODEC_CAP_WOV_LANG_SHM
- [EC_CODEC_WOV_SET_LANG_SHM] = wov_set_lang_shm,
-#else
- [EC_CODEC_WOV_SET_LANG] = wov_set_lang,
-#endif
- [EC_CODEC_WOV_GET_LANG] = wov_get_lang,
- [EC_CODEC_WOV_ENABLE] = wov_enable,
- [EC_CODEC_WOV_DISABLE] = wov_disable,
-#ifdef CONFIG_AUDIO_CODEC_CAP_WOV_AUDIO_SHM
- [EC_CODEC_WOV_READ_AUDIO_SHM] = wov_read_audio_shm,
-#else
- [EC_CODEC_WOV_READ_AUDIO] = wov_read_audio,
-#endif
-};
-
-#ifdef DEBUG_AUDIO_CODEC
-static char *strcmd[] = {
-#ifdef CONFIG_AUDIO_CODEC_CAP_WOV_LANG_SHM
- [EC_CODEC_WOV_SET_LANG_SHM] = "EC_CODEC_WOV_SET_LANG_SHM",
-#else
- [EC_CODEC_WOV_SET_LANG] = "EC_CODEC_WOV_SET_LANG",
-#endif
- [EC_CODEC_WOV_GET_LANG] = "EC_CODEC_WOV_GET_LANG",
- [EC_CODEC_WOV_ENABLE] = "EC_CODEC_WOV_ENABLE",
- [EC_CODEC_WOV_DISABLE] = "EC_CODEC_WOV_DISABLE",
-#ifdef CONFIG_AUDIO_CODEC_CAP_WOV_AUDIO_SHM
- [EC_CODEC_WOV_READ_AUDIO_SHM] = "EC_CODEC_WOV_READ_AUDIO_SHM",
-#else
- [EC_CODEC_WOV_READ_AUDIO] = "EC_CODEC_WOV_READ_AUDIO",
-#endif
-};
-BUILD_ASSERT(ARRAY_SIZE(sub_cmds) == ARRAY_SIZE(strcmd));
-#endif
-
-static enum ec_status wov_host_command(struct host_cmd_handler_args *args)
-{
- const struct ec_param_ec_codec_wov *p = args->params;
-
-#ifdef DEBUG_AUDIO_CODEC
- CPRINTS("WoV subcommand: %s", strcmd[p->cmd]);
-#endif
-
- if (p->cmd < EC_CODEC_WOV_SUBCMD_COUNT && sub_cmds[p->cmd])
- return sub_cmds[p->cmd](args);
-
- return EC_RES_INVALID_PARAM;
-}
-DECLARE_HOST_COMMAND(EC_CMD_EC_CODEC_WOV, wov_host_command, EC_VER_MASK(0));
-
-/*
- * Exported interfaces.
- */
-void audio_codec_wov_task(void *arg)
-{
- uint32_t n, req;
- uint8_t *p;
- int r;
-
- while (1) {
- mutex_lock(&lock);
- if (!wov_enabled) {
- mutex_unlock(&lock);
- task_wait_event(-1);
- continue;
- }
-
-
- /* Clear the buffer if full. */
- if (is_buf_full()) {
- audio_buf_wp = audio_buf_rp;
-
-#ifdef DEBUG_AUDIO_CODEC
- if (hotword_detected)
- CPRINTS("overrun detected");
-#endif
- }
-
- /*
- * Note: sample width is 16-bit.
- *
- * The linear ring buffer wastes one sample bytes to
- * detect buffer full.
- *
- * If buffer is empty, maximum req is BUF_LEN - 2.
- * If wp > rp, wp can fill to the end of linear buffer.
- * If wp < rp, wp can fill up to rp - 2.
- */
- if (audio_buf_wp == audio_buf_rp)
- req = AUDIO_BUF_LEN - MAX(audio_buf_wp, 2);
- else if (audio_buf_wp > audio_buf_rp)
- req = AUDIO_BUF_LEN - audio_buf_wp;
- else
- req = audio_buf_rp - audio_buf_wp - 2;
-
- p = (uint8_t *)audio_codec_wov_audio_buf_addr + audio_buf_wp;
- mutex_unlock(&lock);
-
- n = audio_codec_wov_read(p, req);
- if (n < 0) {
- CPRINTS("failed to read: %d", n);
- break;
- } else if (n == 0) {
- if (audio_codec_wov_enable_notifier() != EC_SUCCESS) {
- CPRINTS("failed to enable_notifier");
- break;
- }
-
- task_wait_event(-1);
- continue;
- }
-
- mutex_lock(&lock);
- audio_buf_wp += n;
- if (audio_buf_wp == AUDIO_BUF_LEN)
- audio_buf_wp = 0;
- mutex_unlock(&lock);
-
- /*
- * GoogleHotwordDspProcess() needs number of samples. In the
- * case, sample is S16_LE. Thus, n / 2.
- */
- if (!hotword_detected &&
- GoogleHotwordDspProcess(p, n / 2, &r)) {
- CPRINTS("hotword detected");
-
- mutex_lock(&lock);
- /*
- * Note: preserve 40% of buf size for AP to read
- * (see go/cros-ec-codec#heading=h.582ga6pgfl2g)
- */
- audio_buf_rp = audio_buf_wp + (AUDIO_BUF_LEN * 2 / 5);
- if (audio_buf_rp >= AUDIO_BUF_LEN)
- audio_buf_rp -= AUDIO_BUF_LEN;
-
- hotword_detected = 1;
- mutex_unlock(&lock);
-
- host_set_single_event(EC_HOST_EVENT_WOV);
- }
-
- /*
- * Reasons to sleep here:
- * 1. read the audio data in a fixed pace (10ms)
- * 2. yield the processor in case of watchdog thought EC crashed
- */
- task_wait_event(10 * MSEC);
- }
-}
diff --git a/common/backlight_lid.c b/common/backlight_lid.c
deleted file mode 100644
index 3b857df592..0000000000
--- a/common/backlight_lid.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Copyright 2013 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.
- */
-
-/* Backlight control based on lid and optional request signal from AP */
-
-#include "common.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "lid_switch.h"
-
-
-/**
- * Activate/Deactivate the backlight GPIO pin considering active high or low.
- */
-void enable_backlight(int enabled)
-{
-#ifdef CONFIG_BACKLIGHT_LID_ACTIVE_LOW
- gpio_set_level(GPIO_ENABLE_BACKLIGHT_L, !enabled);
-#else
- gpio_set_level(GPIO_ENABLE_BACKLIGHT, enabled);
-#endif
-}
-
-/**
- * Update backlight state.
- */
-static void update_backlight(void)
-{
-#ifdef CONFIG_BACKLIGHT_REQ_GPIO
- /* Enable the backlight if lid is open AND requested by AP */
- enable_backlight(lid_is_open() &&
- gpio_get_level(CONFIG_BACKLIGHT_REQ_GPIO));
-#else
- /*
- * Enable backlight if lid is open; this is AND'd with the request from
- * the AP in hardware.
- */
- enable_backlight(lid_is_open());
-#endif
-}
-DECLARE_HOOK(HOOK_LID_CHANGE, update_backlight, HOOK_PRIO_DEFAULT);
-
-/**
- * Initialize backlight module.
- */
-static void backlight_init(void)
-{
- update_backlight();
-
-#ifdef CONFIG_BACKLIGHT_REQ_GPIO
- gpio_enable_interrupt(CONFIG_BACKLIGHT_REQ_GPIO);
-#endif
-}
-DECLARE_HOOK(HOOK_INIT, backlight_init, HOOK_PRIO_DEFAULT);
-
-#ifdef CONFIG_BACKLIGHT_REQ_GPIO
-void backlight_interrupt(enum gpio_signal signal)
-{
- update_backlight();
-}
-#endif
-
-/**
- * Host command to toggle backlight.
- *
- * The requested state will persist until the next lid-switch or request-gpio
- * transition.
- */
-static enum ec_status
-switch_command_enable_backlight(struct host_cmd_handler_args *args)
-{
- const struct ec_params_switch_enable_backlight *p = args->params;
-
- enable_backlight(p->enabled);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_SWITCH_ENABLE_BKLIGHT,
- switch_command_enable_backlight,
- EC_VER_MASK(0));
-
-
diff --git a/common/base32.c b/common/base32.c
deleted file mode 100644
index a6be8409b1..0000000000
--- a/common/base32.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/* Copyright 2017 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.
- */
-
-/* Base-32 encoding/decoding */
-
-#include "common.h"
-#include "base32.h"
-#include "util.h"
-
-static const unsigned char crc5_table1[] = {
- 0x00, 0x0E, 0x1C, 0x12, 0x11, 0x1F, 0x0D, 0x03,
- 0x0B, 0x05, 0x17, 0x19, 0x1A, 0x14, 0x06, 0x08
-};
-
-static const unsigned char crc5_table0[] = {
- 0x00, 0x16, 0x05, 0x13, 0x0A, 0x1C, 0x0F, 0x19,
- 0x14, 0x02, 0x11, 0x07, 0x1E, 0x08, 0x1B, 0x0D
-};
-
-uint8_t crc5_sym(uint8_t sym, uint8_t previous_crc)
-{
- uint8_t tmp = sym ^ previous_crc;
- return crc5_table1[tmp & 0x0F] ^ crc5_table0[(tmp >> 4) & 0x0F];
-}
-
-/* A-Z0-9 with I,O,0,1 removed */
-const char base32_map[33] = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
-
-/**
- * Decode a base32 symbol.
- *
- * @param sym Input symbol
- * @return The symbol value or -1 if error.
- */
-static int decode_sym(int sym)
-{
- int i = 0;
-
- for (i = 0; i < 32; i++) {
- if (sym == base32_map[i])
- return i;
- }
-
- return -1;
-}
-
-int base32_encode(char *dest, int destlen_chars,
- const void *srcbits, int srclen_bits,
- int add_crc_every)
-{
- const uint8_t *src = srcbits;
- int destlen_needed;
- int crc = 0, crc_count = 0;
- int didx = 0;
- int i;
-
- *dest = 0;
-
- /* Make sure destination is big enough */
- destlen_needed = (srclen_bits + 4) / 5; /* Symbols before adding CRC */
- if (add_crc_every) {
- /* Must be an exact number of groups to add CRC */
- if (destlen_needed % add_crc_every)
- return EC_ERROR_INVAL;
- destlen_needed += destlen_needed / add_crc_every;
- }
- destlen_needed++; /* For terminating null */
- if (destlen_chars < destlen_needed)
- return EC_ERROR_INVAL;
-
- for (i = 0; i < srclen_bits; i += 5) {
- int sym;
- int sidx = i / 8;
- int bit_offs = i % 8;
-
- if (bit_offs <= 3) {
- /* Entire symbol fits in that byte */
- sym = src[sidx] >> (3 - bit_offs);
- } else {
- /* Use the bits we have left */
- sym = src[sidx] << (bit_offs - 3);
-
- /* Use the bits from the next byte, if any */
- if (i + 1 < srclen_bits)
- sym |= src[sidx + 1] >> (11 - bit_offs);
- }
-
- sym &= 0x1f;
-
- /* Pad incomplete symbol with 0 bits */
- if (srclen_bits - i < 5)
- sym &= 0x1f << (5 + i - srclen_bits);
-
- dest[didx++] = base32_map[sym];
-
- /* Add CRC if needed */
- if (add_crc_every) {
- crc = crc5_sym(sym, crc);
- if (++crc_count == add_crc_every) {
- dest[didx++] = base32_map[crc];
- crc_count = crc = 0;
- }
- }
- }
-
- /* Terminate string and return */
- dest[didx] = 0;
- return EC_SUCCESS;
-}
-
-int base32_decode(uint8_t *dest, int destlen_bits, const char *src,
- int crc_after_every)
-{
- int crc = 0, crc_count = 0;
- int out_bits = 0;
-
- for (; *src; src++) {
- int sym, sbits, dbits, b;
-
- if (isspace((unsigned char)*src) || *src == '-')
- continue;
-
- sym = decode_sym(*src);
- if (sym < 0)
- return -1; /* Bad input symbol */
-
- /* Check CRC if needed */
- if (crc_after_every) {
- if (crc_count == crc_after_every) {
- if (crc != sym)
- return -1;
- crc_count = crc = 0;
- continue;
- } else {
- crc = crc5_sym(sym, crc);
- crc_count++;
- }
- }
-
- /*
- * Stop if we're out of space. Have to do this after checking
- * the CRC, or we might not check the last CRC.
- */
- if (out_bits >= destlen_bits)
- break;
-
- /* See how many bits we get to use from this symbol */
- sbits = MIN(5, destlen_bits - out_bits);
- if (sbits < 5)
- sym >>= (5 - sbits);
-
- /* Fill up the rest of the current byte */
- dbits = 8 - (out_bits & 7);
- b = MIN(dbits, sbits);
- if (dbits == 8)
- dest[out_bits / 8] = 0; /* Starting a new byte */
- dest[out_bits / 8] |= (sym << (dbits - b)) >> (sbits - b);
- out_bits += b;
- sbits -= b;
-
- /* Start the next byte if there's space */
- if (sbits > 0) {
- dest[out_bits / 8] = sym << (8 - sbits);
- out_bits += sbits;
- }
- }
-
- /* If we have CRCs, should have a full group */
- if (crc_after_every && crc_count)
- return -1;
-
- return out_bits;
-}
diff --git a/common/base_state.c b/common/base_state.c
deleted file mode 100644
index 43e201cab9..0000000000
--- a/common/base_state.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/* Copyright 2018 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.
- */
-
-#include "base_state.h"
-#include "console.h"
-#include "host_command.h"
-#include "hooks.h"
-
-#define CPRINTS(format, args...) cprints(CC_MOTION_LID, format, ## args)
-
-#ifdef CONFIG_BASE_ATTACHED_SWITCH
-/* 1: base attached, 0: otherwise */
-static int base_state;
-
-int base_get_state(void)
-{
- return base_state;
-}
-
-void base_set_state(int state)
-{
- if (base_state == !!state)
- return;
-
- base_state = !!state;
- CPRINTS("base state: %stached", state ? "at" : "de");
- hook_notify(HOOK_BASE_ATTACHED_CHANGE);
-
- /* Notify host of mode change. This likely will wake it up. */
- host_set_single_event(EC_HOST_EVENT_MODE_CHANGE);
-}
-#endif
-
-static int command_setbasestate(int argc, char **argv)
-{
- if (argc != 2)
- return EC_ERROR_PARAM_COUNT;
- if (argv[1][0] == 'a')
- base_force_state(EC_SET_BASE_STATE_ATTACH);
- else if (argv[1][0] == 'd')
- base_force_state(EC_SET_BASE_STATE_DETACH);
- else if (argv[1][0] == 'r')
- base_force_state(EC_SET_BASE_STATE_RESET);
- else
- return EC_ERROR_PARAM1;
-
- return EC_SUCCESS;
-
-}
-DECLARE_CONSOLE_COMMAND(basestate, command_setbasestate,
- "[attach | detach | reset]",
- "Manually force base state to attached, detached or reset.");
-
-static enum ec_status hostcmd_setbasestate(struct host_cmd_handler_args *args)
-{
- const struct ec_params_set_base_state *params = args->params;
-
- if (params->cmd > EC_SET_BASE_STATE_RESET)
- return EC_RES_INVALID_PARAM;
-
- base_force_state(params->cmd);
-
- return EC_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_SET_BASE_STATE, hostcmd_setbasestate,
- EC_VER_MASK(0));
diff --git a/common/battery.c b/common/battery.c
deleted file mode 100644
index 6791e4d3a2..0000000000
--- a/common/battery.c
+++ /dev/null
@@ -1,812 +0,0 @@
-/* Copyright 2012 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.
- *
- * Common battery command.
- */
-
-#include "battery.h"
-#include "charge_manager.h"
-#include "charge_state.h"
-#include "common.h"
-#include "console.h"
-#include "ec_ec_comm_client.h"
-#include "extpower.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "math_util.h"
-#include "timer.h"
-#include "usb_pd.h"
-#include "util.h"
-#include "watchdog.h"
-
-#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args)
-#define CUTOFFPRINTS(info) CPRINTS("%s %s", "Battery cut off", info)
-
-/* See config.h for details */
-const static int batt_host_full_factor = CONFIG_BATT_HOST_FULL_FACTOR;
-const static int batt_host_shutdown_pct = CONFIG_BATT_HOST_SHUTDOWN_PERCENTAGE;
-
-#ifdef CONFIG_BATTERY_V2
-/*
- * Store battery information in these 2 structures. Main (lid) battery is always
- * at index 0, and secondary (base) battery at index 1.
- */
-struct ec_response_battery_static_info_v1 battery_static[CONFIG_BATTERY_COUNT];
-struct ec_response_battery_dynamic_info battery_dynamic[CONFIG_BATTERY_COUNT];
-#endif
-
-#ifdef CONFIG_BATTERY_CUT_OFF
-
-#ifndef CONFIG_BATTERY_CUTOFF_DELAY_US
-#define CONFIG_BATTERY_CUTOFF_DELAY_US (1 * SECOND)
-#endif
-
-static enum battery_cutoff_states battery_cutoff_state =
- BATTERY_CUTOFF_STATE_NORMAL;
-
-#endif
-
-#ifdef CONFIG_BATTERY_PRESENT_GPIO
-#ifdef CONFIG_BATTERY_PRESENT_CUSTOM
-#error "Don't define both CONFIG_BATTERY_PRESENT_CUSTOM and" \
- "CONFIG_BATTERY_PRESENT_GPIO"
-#endif
-/**
- * Physical detection of battery.
- */
-enum battery_present battery_is_present(void)
-{
- /* The GPIO is low when the battery is present */
- return gpio_get_level(CONFIG_BATTERY_PRESENT_GPIO) ? BP_NO : BP_YES;
-}
-#endif
-
-static const char *get_error_text(int rv)
-{
- if (rv == EC_ERROR_UNIMPLEMENTED)
- return "(unsupported)";
- else
- return "(error)";
-}
-
-static void print_item_name(const char *name)
-{
- ccprintf(" %-11s", name);
-}
-
-static int check_print_error(int rv)
-{
- if (rv != EC_SUCCESS)
- ccprintf("%s\n", get_error_text(rv));
- return rv == EC_SUCCESS;
-}
-
-static void print_battery_status(void)
-{
- static const char * const st[] = {"EMPTY", "FULL", "DCHG", "INIT",};
- static const char * const al[] = {"RT", "RC", "--", "TD",
- "OT", "--", "TC", "OC"};
-
- int value, i;
-
- print_item_name("Status:");
- if (check_print_error(battery_status(&value))) {
- ccprintf("0x%04x", value);
-
- /* bits 0-3 are only valid when the previous transaction
- * failed, so ignore them */
-
- /* bits 4-7 are status */
- for (i = 0; i < 4; i++)
- if (value & (1 << (i+4)))
- ccprintf(" %s", st[i]);
-
- /* bits 15-8 are alarms */
- for (i = 0; i < 8; i++)
- if (value & (1 << (i+8)))
- ccprintf(" %s", al[i]);
-
- ccprintf("\n");
- }
-}
-
-static void print_battery_strings(void)
-{
- char text[32];
-
- print_item_name("Manuf:");
- if (check_print_error(battery_manufacturer_name(text, sizeof(text))))
- ccprintf("%s\n", text);
-
- print_item_name("Device:");
- if (check_print_error(battery_device_name(text, sizeof(text))))
- ccprintf("%s\n", text);
-
- print_item_name("Chem:");
- if (check_print_error(battery_device_chemistry(text, sizeof(text))))
- ccprintf("%s\n", text);
-}
-
-static void print_battery_params(void)
-{
-#if defined(HAS_TASK_CHARGER)
- /* Ask charger so that we don't need to ask battery again. */
- const struct batt_params *batt = charger_current_battery_params();
-#else
- /* This is for test code, where doesn't have charger task. */
- struct batt_params _batt;
- const struct batt_params *batt = &_batt;
-
- battery_get_params(&_batt);
-#endif
-
- print_item_name("Param flags:");
- ccprintf("%08x\n", batt->flags);
-
- print_item_name("Temp:");
- ccprintf("0x%04x = %.1d K (%.1d C)\n",
- batt->temperature,
- batt->temperature,
- batt->temperature - 2731);
-
- print_item_name("V:");
- ccprintf("0x%04x = %d mV\n", batt->voltage, batt->voltage);
-
- print_item_name("V-desired:");
- ccprintf("0x%04x = %d mV\n", batt->desired_voltage,
- batt->desired_voltage);
-
- print_item_name("I:");
- ccprintf("0x%04x = %d mA", batt->current & 0xffff, batt->current);
- if (batt->current > 0)
- ccputs("(CHG)");
- else if (batt->current < 0)
- ccputs("(DISCHG)");
- ccputs("\n");
-
- print_item_name("I-desired:");
- ccprintf("0x%04x = %d mA\n", batt->desired_current,
- batt->desired_current);
-
- print_item_name("Charging:");
- ccprintf("%sAllowed\n",
- batt->flags & BATT_FLAG_WANT_CHARGE ? "" : "Not ");
-
- print_item_name("Charge:");
- ccprintf("%d %%\n", batt->state_of_charge);
-
- if (IS_ENABLED(CONFIG_CHARGER)) {
- int value;
-
- print_item_name(" Display:");
- value = charge_get_display_charge();
- ccprintf("%d.%d %%\n", value / 10, value % 10);
- }
-}
-
-static void print_battery_info(void)
-{
- int value;
- int hour, minute;
-
- print_item_name("Serial:");
- if (check_print_error(battery_serial_number(&value)))
- ccprintf("0x%04x\n", value);
-
- print_item_name("V-design:");
- if (check_print_error(battery_design_voltage(&value)))
- ccprintf("0x%04x = %d mV\n", value, value);
-
- print_item_name("Mode:");
- if (check_print_error(battery_get_mode(&value)))
- ccprintf("0x%04x\n", value);
-
- print_item_name("Abs charge:");
- if (check_print_error(battery_state_of_charge_abs(&value)))
- ccprintf("%d %%\n", value);
-
- print_item_name("Remaining:");
- if (check_print_error(battery_remaining_capacity(&value)))
- ccprintf("%d mAh\n", value);
-
- print_item_name("Cap-full:");
- if (check_print_error(battery_full_charge_capacity(&value)))
- ccprintf("%d mAh\n", value);
-
- print_item_name(" Design:");
- if (check_print_error(battery_design_capacity(&value)))
- ccprintf("%d mAh\n", value);
-
- print_item_name("Time-full:");
- if (check_print_error(battery_time_to_full(&value))) {
- if (value == 65535) {
- hour = 0;
- minute = 0;
- } else {
- hour = value / 60;
- minute = value % 60;
- }
- ccprintf("%dh:%d\n", hour, minute);
- }
-
- print_item_name(" Empty:");
- if (check_print_error(battery_time_to_empty(&value))) {
- if (value == 65535) {
- hour = 0;
- minute = 0;
- } else {
- hour = value / 60;
- minute = value % 60;
- }
- ccprintf("%dh:%d\n", hour, minute);
- }
-
- print_item_name("full_factor:");
- ccprintf("0.%d\n", batt_host_full_factor);
-
- print_item_name("shutdown_soc:");
- ccprintf("%d %%\n", batt_host_shutdown_pct);
-}
-
-void print_battery_debug(void)
-{
- print_battery_status();
- print_battery_params();
- print_battery_strings();
- print_battery_info();
-}
-
-static int command_battery(int argc, char **argv)
-{
- int repeat = 1;
- int loop;
- int sleep_ms = 0;
- char *e;
-
- if (argc > 1) {
- repeat = strtoi(argv[1], &e, 0);
- if (*e) {
- ccputs("Invalid repeat count\n");
- return EC_ERROR_INVAL;
- }
- }
-
- if (argc > 2) {
- sleep_ms = strtoi(argv[2], &e, 0);
- if (*e) {
- ccputs("Invalid sleep ms\n");
- return EC_ERROR_INVAL;
- }
- }
-
- for (loop = 0; loop < repeat; loop++) {
- print_battery_debug();
-
- /*
- * Running with a high repeat count will take so long the
- * watchdog timer fires. So reset the watchdog timer each
- * iteration.
- */
- watchdog_reload();
-
- if (sleep_ms)
- msleep(sleep_ms);
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(battery, command_battery,
- "<repeat_count> <sleep_ms>",
- "Print battery info");
-
-#ifdef CONFIG_BATTERY_CUT_OFF
-int battery_is_cut_off(void)
-{
- return (battery_cutoff_state == BATTERY_CUTOFF_STATE_CUT_OFF);
-}
-
-static void pending_cutoff_deferred(void)
-{
- int rv;
-
- rv = board_cut_off_battery();
-
- if (rv == EC_RES_SUCCESS) {
- CUTOFFPRINTS("succeeded.");
- battery_cutoff_state = BATTERY_CUTOFF_STATE_CUT_OFF;
- } else {
- CUTOFFPRINTS("failed!");
- battery_cutoff_state = BATTERY_CUTOFF_STATE_NORMAL;
- }
-}
-DECLARE_DEFERRED(pending_cutoff_deferred);
-
-static void clear_pending_cutoff(void)
-{
- if (extpower_is_present()) {
- battery_cutoff_state = BATTERY_CUTOFF_STATE_NORMAL;
- hook_call_deferred(&pending_cutoff_deferred_data, -1);
- }
-}
-DECLARE_HOOK(HOOK_AC_CHANGE, clear_pending_cutoff, HOOK_PRIO_DEFAULT);
-
-static enum ec_status battery_command_cutoff(struct host_cmd_handler_args *args)
-{
- const struct ec_params_battery_cutoff *p;
- int rv;
-
- if (args->version == 1) {
- p = args->params;
- if (p->flags & EC_BATTERY_CUTOFF_FLAG_AT_SHUTDOWN) {
- battery_cutoff_state = BATTERY_CUTOFF_STATE_PENDING;
- CUTOFFPRINTS("at-shutdown is scheduled");
- return EC_RES_SUCCESS;
- }
- }
-
- rv = board_cut_off_battery();
- if (rv == EC_RES_SUCCESS) {
- CUTOFFPRINTS("is successful.");
- battery_cutoff_state = BATTERY_CUTOFF_STATE_CUT_OFF;
- } else {
- CUTOFFPRINTS("has failed.");
- }
-
- return rv;
-}
-DECLARE_HOST_COMMAND(EC_CMD_BATTERY_CUT_OFF, battery_command_cutoff,
- EC_VER_MASK(0) | EC_VER_MASK(1));
-
-static void check_pending_cutoff(void)
-{
- if (battery_cutoff_state == BATTERY_CUTOFF_STATE_PENDING) {
- CPRINTS("Cutting off battery in %d second(s)",
- CONFIG_BATTERY_CUTOFF_DELAY_US / SECOND);
- hook_call_deferred(&pending_cutoff_deferred_data,
- CONFIG_BATTERY_CUTOFF_DELAY_US);
- }
-}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, check_pending_cutoff, HOOK_PRIO_LAST);
-
-static int command_cutoff(int argc, char **argv)
-{
- int rv;
-
- if (argc > 1) {
- if (!strcasecmp(argv[1], "at-shutdown")) {
- battery_cutoff_state = BATTERY_CUTOFF_STATE_PENDING;
- return EC_SUCCESS;
- } else {
- return EC_ERROR_INVAL;
- }
- }
-
- rv = board_cut_off_battery();
- if (rv == EC_RES_SUCCESS) {
- ccprints("Battery cut off");
- battery_cutoff_state = BATTERY_CUTOFF_STATE_CUT_OFF;
- return EC_SUCCESS;
- }
-
- return EC_ERROR_UNKNOWN;
-}
-DECLARE_CONSOLE_COMMAND(cutoff, command_cutoff,
- "[at-shutdown]",
- "Cut off the battery output");
-#else
-int battery_is_cut_off(void)
-{
- return 0; /* Always return NOT cut off */
-}
-#endif /* CONFIG_BATTERY_CUT_OFF */
-
-#ifdef CONFIG_BATTERY_VENDOR_PARAM
-static int console_command_battery_vendor_param(int argc, char **argv)
-{
- uint32_t param;
- uint32_t value;
- char *e;
- int rv;
-
- if (argc < 2)
- return EC_ERROR_INVAL;
-
- param = strtoi(argv[1], &e, 0);
- if (*e) {
- ccputs("Invalid param\n");
- return EC_ERROR_INVAL;
- }
-
- if (argc > 2) {
- value = strtoi(argv[2], &e, 0);
- if (*e) {
- ccputs("Invalid value\n");
- return EC_ERROR_INVAL;
- }
- rv = battery_set_vendor_param(param, value);
- if (rv != EC_SUCCESS)
- return rv;
- }
-
- rv = battery_get_vendor_param(param, &value);
- if (rv != EC_SUCCESS)
- return rv;
-
- ccprintf("0x%08x\n", value);
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(battparam, console_command_battery_vendor_param,
- "<param> [value]",
- "Get or set battery vendor parameters");
-
-static enum ec_status
-host_command_battery_vendor_param(struct host_cmd_handler_args *args)
-{
- int rv;
- const struct ec_params_battery_vendor_param *p = args->params;
- struct ec_response_battery_vendor_param *r = args->response;
-
- args->response_size = sizeof(*r);
-
- if (p->mode != BATTERY_VENDOR_PARAM_MODE_GET &&
- p->mode != BATTERY_VENDOR_PARAM_MODE_SET)
- return EC_RES_INVALID_PARAM;
-
- if (p->mode == BATTERY_VENDOR_PARAM_MODE_SET) {
- rv = battery_set_vendor_param(p->param, p->value);
- if (rv != EC_SUCCESS)
- return rv;
- }
-
- rv = battery_get_vendor_param(p->param, &r->value);
- return rv;
-}
-DECLARE_HOST_COMMAND(EC_CMD_BATTERY_VENDOR_PARAM,
- host_command_battery_vendor_param,
- EC_VER_MASK(0));
-#endif /* CONFIG_BATTERY_VENDOR_PARAM */
-
-#ifdef CONFIG_BATTERY_V2
-#ifdef CONFIG_HOSTCMD_BATTERY_V2
-static void battery_update(enum battery_index i);
-static enum ec_status
-host_command_battery_get_static(struct host_cmd_handler_args *args)
-{
- const struct ec_params_battery_static_info *p = args->params;
- struct ec_response_battery_static_info_v1 *bat;
-
- if (p->index < 0 || p->index >= CONFIG_BATTERY_COUNT)
- return EC_RES_INVALID_PARAM;
- bat = &battery_static[p->index];
-
- battery_update(p->index);
- if (args->version == 0) {
- struct ec_response_battery_static_info *r = args->response;
-
- args->response_size = sizeof(*r);
- r->design_capacity = bat->design_capacity;
- r->design_voltage = bat->design_voltage;
- r->cycle_count = bat->cycle_count;
-
- /* Truncate strings to reduced v0 size */
- memcpy(&r->manufacturer, &bat->manufacturer_ext,
- sizeof(r->manufacturer));
- r->manufacturer[sizeof(r->manufacturer) - 1] = 0;
- memcpy(&r->model, &bat->model_ext, sizeof(r->model));
- r->model[sizeof(r->model) - 1] = 0;
- memcpy(&r->serial, &bat->serial_ext, sizeof(r->serial));
- r->serial[sizeof(r->serial) - 1] = 0;
- memcpy(&r->type, &bat->type_ext, sizeof(r->type));
- r->type[sizeof(r->type) - 1] = 0;
- } else {
- /* v1 command stores the same data internally */
- struct ec_response_battery_static_info_v1 *r = args->response;
-
- args->response_size = sizeof(*r);
- memcpy(r, bat, sizeof(*r));
- }
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_BATTERY_GET_STATIC,
- host_command_battery_get_static,
- EC_VER_MASK(0) | EC_VER_MASK(1));
-
-static enum ec_status
-host_command_battery_get_dynamic(struct host_cmd_handler_args *args)
-{
- const struct ec_params_battery_dynamic_info *p = args->params;
- struct ec_response_battery_dynamic_info *r = args->response;
-
- if (p->index < 0 || p->index >= CONFIG_BATTERY_COUNT)
- return EC_RES_INVALID_PARAM;
-
- args->response_size = sizeof(*r);
- memcpy(r, &battery_dynamic[p->index], sizeof(*r));
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_BATTERY_GET_DYNAMIC,
- host_command_battery_get_dynamic,
- EC_VER_MASK(0));
-#endif /* CONFIG_HOSTCMD_BATTERY_V2 */
-
-#ifdef HAS_TASK_HOSTCMD
-static void battery_update(enum battery_index i)
-{
- char *batt_str;
- int *memmap_dcap = (int *)host_get_memmap(EC_MEMMAP_BATT_DCAP);
- int *memmap_dvlt = (int *)host_get_memmap(EC_MEMMAP_BATT_DVLT);
- int *memmap_ccnt = (int *)host_get_memmap(EC_MEMMAP_BATT_CCNT);
- int *memmap_volt = (int *)host_get_memmap(EC_MEMMAP_BATT_VOLT);
- int *memmap_rate = (int *)host_get_memmap(EC_MEMMAP_BATT_RATE);
- int *memmap_cap = (int *)host_get_memmap(EC_MEMMAP_BATT_CAP);
- int *memmap_lfcc = (int *)host_get_memmap(EC_MEMMAP_BATT_LFCC);
- uint8_t *memmap_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG);
-
- /* Smart battery serial number is 16 bits */
- batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_SERIAL);
- memcpy(batt_str, battery_static[i].serial_ext, EC_MEMMAP_TEXT_MAX);
- batt_str[EC_MEMMAP_TEXT_MAX - 1] = 0;
-
- /* Design Capacity of Full */
- *memmap_dcap = battery_static[i].design_capacity;
-
- /* Design Voltage */
- *memmap_dvlt = battery_static[i].design_voltage;
-
- /* Cycle Count */
- *memmap_ccnt = battery_static[i].cycle_count;
-
- /* Battery Manufacturer string */
- batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MFGR);
- memcpy(batt_str, battery_static[i].manufacturer_ext,
- EC_MEMMAP_TEXT_MAX);
- batt_str[EC_MEMMAP_TEXT_MAX - 1] = 0;
-
- /* Battery Model string */
- batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MODEL);
- memcpy(batt_str, battery_static[i].model_ext, EC_MEMMAP_TEXT_MAX);
- batt_str[EC_MEMMAP_TEXT_MAX - 1] = 0;
-
- /* Battery Type string */
- batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_TYPE);
- memcpy(batt_str, battery_static[i].type_ext, EC_MEMMAP_TEXT_MAX);
- batt_str[EC_MEMMAP_TEXT_MAX - 1] = 0;
-
- *memmap_volt = battery_dynamic[i].actual_voltage;
- *memmap_rate = battery_dynamic[i].actual_current;
- *memmap_cap = battery_dynamic[i].remaining_capacity;
- *memmap_lfcc = battery_dynamic[i].full_capacity;
- *memmap_flags = battery_dynamic[i].flags;
-}
-
-void battery_memmap_refresh(enum battery_index index)
-{
- if (*host_get_memmap(EC_MEMMAP_BATT_INDEX) == index)
- battery_update(index);
-}
-
-void battery_memmap_set_index(enum battery_index index)
-{
- if (*host_get_memmap(EC_MEMMAP_BATT_INDEX) == index)
- return;
-
- *host_get_memmap(EC_MEMMAP_BATT_INDEX) = BATT_IDX_INVALID;
- if (index < 0 || index >= CONFIG_BATTERY_COUNT)
- return;
-
- battery_update(index);
- *host_get_memmap(EC_MEMMAP_BATT_INDEX) = index;
-}
-
-static void battery_init(void)
-{
- *host_get_memmap(EC_MEMMAP_BATT_INDEX) = BATT_IDX_INVALID;
- *host_get_memmap(EC_MEMMAP_BATT_COUNT) = CONFIG_BATTERY_COUNT;
- *host_get_memmap(EC_MEMMAP_BATTERY_VERSION) = 2;
-
- battery_memmap_set_index(BATT_IDX_MAIN);
-}
-DECLARE_HOOK(HOOK_INIT, battery_init, HOOK_PRIO_DEFAULT);
-#endif /* HAS_TASK_HOSTCMD */
-#endif /* CONFIG_BATTERY_V2 */
-
-void battery_compensate_params(struct batt_params *batt)
-{
- int numer, denom;
- int *remain = &(batt->remaining_capacity);
- int full = batt->full_capacity;
-
- if ((batt->flags & BATT_FLAG_BAD_FULL_CAPACITY) ||
- (batt->flags & BATT_FLAG_BAD_REMAINING_CAPACITY))
- return;
-
- if (*remain <= 0 || full <= 0)
- return;
-
- /* Some batteries don't update full capacity as often. */
- if (*remain > full)
- *remain = full;
-
- /*
- * EC calculates the display SoC like how Powerd used to do. Powerd
- * reads the display SoC from the EC. This design allows the system to
- * behave consistently on a single SoC value across all power states.
- *
- * Display SoC is computed as follows:
- *
- * actual_soc = 100 * remain / full
- *
- * actual_soc - shutdown_pct
- * display_soc = --------------------------- x 1000
- * full_factor - shutdown_pct
- *
- * (100 * remain / full) - shutdown_pct
- * = ------------------------------------ x 1000
- * full_factor - shutdown_pct
- *
- * 100 x remain - full x shutdown_pct
- * = ----------------------------------- x 1000
- * full x (full_factor - shutdown_pct)
- */
- numer = 1000 * ((100 * *remain) - (full * batt_host_shutdown_pct));
- denom = full * (batt_host_full_factor - batt_host_shutdown_pct);
- /* Rounding (instead of truncating) */
- batt->display_charge = (numer + denom / 2) / denom;
- if (batt->display_charge < 0)
- batt->display_charge = 0;
- if (batt->display_charge > 1000)
- batt->display_charge = 1000;
-}
-
-#ifdef CONFIG_CHARGER
-static enum ec_status battery_display_soc(struct host_cmd_handler_args *args)
-{
- struct ec_response_display_soc *r = args->response;
-
- r->display_soc = charge_get_display_charge();
- r->full_factor = batt_host_full_factor * 10;
- r->shutdown_soc = batt_host_shutdown_pct * 10;
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_DISPLAY_SOC, battery_display_soc, EC_VER_MASK(0));
-#endif
-
-__overridable void board_battery_compensate_params(struct batt_params *batt)
-{
-}
-
-__attribute__((weak)) int get_battery_manufacturer_name(char *dest, int size)
-{
- strzcpy(dest, "<unkn>", size);
- return EC_SUCCESS;
-}
-
-__overridable int battery_get_avg_voltage(void)
-{
- return -EC_ERROR_UNIMPLEMENTED;
-}
-
-__overridable int battery_get_avg_current(void)
-{
- return -EC_ERROR_UNIMPLEMENTED;
-}
-
-int battery_manufacturer_name(char *dest, int size)
-{
- return get_battery_manufacturer_name(dest, size);
-}
-
-__overridable enum battery_disconnect_state battery_get_disconnect_state(void)
-{
- return BATTERY_NOT_DISCONNECTED;
-}
-
-#ifdef CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV
-
-#if CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV < 5000 || \
- CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV >= PD_MAX_VOLTAGE_MV
- #error "Voltage limit must be between 5000 and PD_MAX_VOLTAGE_MV"
-#endif
-
-#if !((defined(CONFIG_USB_PD_TCPMV1) && defined(CONFIG_USB_PD_DUAL_ROLE)) || \
- (defined(CONFIG_USB_PD_TCPMV2) && defined(CONFIG_USB_PE_SM)))
- #error "Voltage reducing requires TCPM with Policy Engine"
-#endif
-
-/*
- * Returns true if input voltage should be reduced (chipset is in S5/G3) and
- * battery is full, otherwise returns false
- */
-static bool board_wants_reduced_input_voltage(void) {
- struct batt_params batt;
-
- /* Chipset not in S5/G3, so we don't want to reduce voltage */
- if (!chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF))
- return false;
-
- battery_get_params(&batt);
-
- /* Battery needs charge, so we don't want to reduce voltage */
- if (batt.flags & BATT_FLAG_WANT_CHARGE)
- return false;
-
- return true;
-}
-
-static void reduce_input_voltage_when_full(void)
-{
- static int saved_input_voltage = -1;
- int max_pd_voltage_mv = pd_get_max_voltage();
- int port;
-
- port = charge_manager_get_active_charge_port();
- if (port < 0 || port >= board_get_usb_pd_port_count())
- return;
-
- if (board_wants_reduced_input_voltage()) {
- /*
- * Board wants voltage to be reduced. Apply limit if current
- * voltage is different. Save current voltage, it will be
- * restored when board wants to stop reducing input voltage.
- */
- if (max_pd_voltage_mv !=
- CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV) {
- saved_input_voltage = max_pd_voltage_mv;
- max_pd_voltage_mv =
- CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV;
- }
- } else if (saved_input_voltage != -1) {
- /*
- * Board doesn't want to reduce input voltage. If current
- * voltage is reduced we will restore previously saved voltage.
- * If current voltage is different we will respect newer value.
- */
- if (max_pd_voltage_mv ==
- CONFIG_BATT_FULL_CHIPSET_OFF_INPUT_LIMIT_MV)
- max_pd_voltage_mv = saved_input_voltage;
-
- saved_input_voltage = -1;
- }
-
- if (pd_get_max_voltage() != max_pd_voltage_mv)
- pd_set_external_voltage_limit(port, max_pd_voltage_mv);
-}
-DECLARE_HOOK(HOOK_AC_CHANGE, reduce_input_voltage_when_full,
- HOOK_PRIO_DEFAULT);
-DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, reduce_input_voltage_when_full,
- HOOK_PRIO_DEFAULT);
-DECLARE_HOOK(HOOK_CHIPSET_STARTUP, reduce_input_voltage_when_full,
- HOOK_PRIO_DEFAULT);
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, reduce_input_voltage_when_full,
- HOOK_PRIO_DEFAULT);
-#endif
-
-void battery_validate_params(struct batt_params *batt)
-{
- /*
- * TODO(crosbug.com/p/27527). Sometimes the battery thinks its
- * temperature is 6280C, which seems a bit high. Let's ignore
- * anything above the boiling point of tungsten until this bug
- * is fixed. If the battery is really that warm, we probably
- * have more urgent problems.
- */
- if (batt->temperature > CELSIUS_TO_DECI_KELVIN(5660)) {
- CPRINTS("ignoring ridiculous batt.temp of %dC",
- DECI_KELVIN_TO_CELSIUS(batt->temperature));
- batt->flags |= BATT_FLAG_BAD_TEMPERATURE;
- }
-
- /* If the battery thinks it's above 100%, don't believe it */
- if (batt->state_of_charge > 100) {
- CPRINTS("ignoring ridiculous batt.soc of %d%%",
- batt->state_of_charge);
- batt->flags |= BATT_FLAG_BAD_STATE_OF_CHARGE;
- }
-}
diff --git a/common/battery_fuel_gauge.c b/common/battery_fuel_gauge.c
deleted file mode 100644
index 528713d68f..0000000000
--- a/common/battery_fuel_gauge.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/* Copyright 2018 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.
- *
- * Battery fuel gauge parameters
- */
-
-#include "battery_fuel_gauge.h"
-#include "battery_smart.h"
-#include "console.h"
-#include "hooks.h"
-#include "i2c.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args)
-
-
-/* Get type of the battery connected on the board */
-static int get_battery_type(void)
-{
- char manuf_name[32], device_name[32];
- int i;
- static enum battery_type battery_type = BATTERY_TYPE_COUNT;
-
- /*
- * If battery_type is not the default value, then can return here
- * as there is no need to query the fuel gauge.
- */
- if (battery_type != BATTERY_TYPE_COUNT)
- return battery_type;
-
- /* Get the manufacturer name. If can't read then just exit */
- 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.
- */
- 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;
- }
-
- CPRINTS("found batt:%s", fuel_gauge->manuf_name);
- battery_type = i;
- break;
- }
-
- return battery_type;
-}
-
-__overridable int board_get_default_battery_type(void)
-{
- return DEFAULT_BATTERY_TYPE;
-}
-
-/*
- * Initialize the battery type for the board.
- *
- * The first call to battery_get_info() is when the charger task starts, so
- * initialize the battery type as soon as I2C is initialized.
- */
-static void init_battery_type(void)
-{
- if (get_battery_type() == BATTERY_TYPE_COUNT)
- CPRINTS("battery not found");
-}
-DECLARE_HOOK(HOOK_INIT, init_battery_type, HOOK_PRIO_INIT_I2C + 1);
-
-static inline const struct board_batt_params *get_batt_params(void)
-{
- int type = get_battery_type();
-
- return &board_battery_info[type == BATTERY_TYPE_COUNT ?
- board_get_default_battery_type() : type];
-}
-
-const struct battery_info *battery_get_info(void)
-{
- return &get_batt_params()->batt_info;
-}
-
-int cut_off_battery_block_write(const struct ship_mode_info *ship_mode)
-{
- int rv;
-
- uint8_t cutdata[3] = {
- 0x02,
- ship_mode->reg_data[0] & 0xFF,
- ship_mode->reg_data[0] >> 8,
- };
-
- /* SMBus protocols are block write, which include byte count
- * byte. Byte count segments are required to communicate
- * required action and the number of data bytes.
- * Due to ship mode command requires writing data values twice
- * to cutoff the battery, so byte count is 0x02.
- */
- rv = sb_write_block(ship_mode->reg_addr, cutdata, sizeof(cutdata));
- if (rv)
- return rv;
-
- /* Use the next set of values */
- cutdata[1] = ship_mode->reg_data[1] & 0xFF;
- cutdata[2] = ship_mode->reg_data[1] >> 8;
-
- return sb_write_block(ship_mode->reg_addr, cutdata, sizeof(cutdata));
-}
-
-int cut_off_battery_sb_write(const struct ship_mode_info *ship_mode)
-{
- int rv;
-
- /* Ship mode command requires writing 2 data values */
- rv = sb_write(ship_mode->reg_addr, ship_mode->reg_data[0]);
- if (rv)
- return rv;
-
- return sb_write(ship_mode->reg_addr, ship_mode->reg_data[1]);
-}
-
-int board_cut_off_battery(void)
-{
- int rv;
- int type = get_battery_type();
-
- /* If battery type is unknown can't send ship mode command */
- if (type == BATTERY_TYPE_COUNT)
- return EC_RES_ERROR;
-
- if (board_battery_info[type].fuel_gauge.ship_mode.wb_support)
- rv = cut_off_battery_block_write(
- &board_battery_info[type].fuel_gauge.ship_mode);
- else
- rv = cut_off_battery_sb_write(
- &board_battery_info[type].fuel_gauge.ship_mode);
-
- return rv ? EC_RES_ERROR : EC_RES_SUCCESS;
-}
-
-enum ec_error_list battery_sleep_fuel_gauge(void)
-{
- const struct sleep_mode_info *sleep_command;
- int type = get_battery_type();
-
- /* Sleep entry command must be supplied as it will vary by gauge */
- if (type == BATTERY_TYPE_COUNT)
- return EC_ERROR_UNKNOWN;
-
- sleep_command = &board_battery_info[type].fuel_gauge.sleep_mode;
-
- if (!sleep_command->sleep_supported)
- return EC_ERROR_UNIMPLEMENTED;
-
- return sb_write(sleep_command->reg_addr, sleep_command->reg_data);
-}
-
-static enum ec_error_list battery_get_fet_status_regval(int *regval)
-{
- int rv;
- uint8_t data[6];
- int type = get_battery_type();
-
- /* If battery type is not known, can't check CHG/DCHG FETs */
- if (type == BATTERY_TYPE_COUNT) {
- /* Still don't know, so return here */
- return EC_ERROR_BUSY;
- }
-
- /* Read the status of charge/discharge FETs */
- if (board_battery_info[type].fuel_gauge.fet.mfgacc_support == 1) {
- rv = sb_read_mfgacc(PARAM_OPERATION_STATUS,
- SB_ALT_MANUFACTURER_ACCESS, data,
- sizeof(data));
- /* Get the lowest 16bits of the OperationStatus() data */
- *regval = data[2] | data[3] << 8;
- } else
- rv = sb_read(board_battery_info[type].fuel_gauge.fet.reg_addr,
- regval);
-
- return rv;
-}
-
-int battery_is_charge_fet_disabled(void)
-{
- int rv;
- int reg;
- int type = get_battery_type();
-
- /* If battery type is not known, can't check CHG/DCHG FETs */
- if (type == BATTERY_TYPE_COUNT) {
- /* Still don't know, so return here */
- return -1;
- }
-
- /*
- * If the CFET mask hasn't been defined, assume that it's not disabled.
- */
- if (!board_battery_info[type].fuel_gauge.fet.cfet_mask)
- return 0;
-
- rv = battery_get_fet_status_regval(&reg);
- if (rv)
- return -1;
-
- return (reg & board_battery_info[type].fuel_gauge.fet.cfet_mask) ==
- board_battery_info[type].fuel_gauge.fet.cfet_off_val;
-}
-
-/*
- * This function checks the charge/discharge FET status bits. Each battery type
- * supported provides the register address, mask, and disconnect value for these
- * 2 FET status bits. If the FET status matches the disconnected value, then
- * BATTERY_DISCONNECTED is returned. This function is required to handle the
- * cases when the fuel gauge is awake and will return a non-zero state of
- * charge, but is not able yet to provide power (i.e. discharge FET is not
- * active). By returning BATTERY_DISCONNECTED the AP will not be powered up
- * until either the external charger is able to provided enough power, or
- * the battery is able to provide power and thus prevent a brownout when the
- * AP is powered on by the EC.
- */
-enum battery_disconnect_state battery_get_disconnect_state(void)
-{
- int reg;
- int type = get_battery_type();
-
- /* If battery type is not known, can't check CHG/DCHG FETs */
- if (type == BATTERY_TYPE_COUNT) {
- /* Still don't know, so return here */
- return BATTERY_DISCONNECT_ERROR;
- }
-
- if (battery_get_fet_status_regval(&reg))
- return BATTERY_DISCONNECT_ERROR;
-
- if ((reg & board_battery_info[type].fuel_gauge.fet.reg_mask) ==
- board_battery_info[type].fuel_gauge.fet.disconnect_val) {
- CPRINTS("Batt disconnected: reg 0x%04x mask 0x%04x disc 0x%04x",
- reg,
- board_battery_info[type].fuel_gauge.fet.reg_mask,
- board_battery_info[type].fuel_gauge.fet.disconnect_val);
- return BATTERY_DISCONNECTED;
- }
-
- return BATTERY_NOT_DISCONNECTED;
-}
-
-#ifdef CONFIG_BATTERY_MEASURE_IMBALANCE
-int battery_imbalance_mv(void)
-{
- int type = get_battery_type();
-
- /*
- * If battery type is unknown, we cannot safely access non-standard
- * registers.
- */
- return (type == BATTERY_TYPE_COUNT) ? 0 :
- board_battery_info[type].fuel_gauge.imbalance_mv();
-}
-
-int battery_default_imbalance_mv(void)
-{
- return 0;
-}
-#endif /* CONFIG_BATTERY_MEASURE_IMBALANCE */
diff --git a/common/blink.c b/common/blink.c
deleted file mode 100644
index ed16146f5a..0000000000
--- a/common/blink.c
+++ /dev/null
@@ -1,30 +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.
- */
-
-/* This is a confidence check program for boards that have LEDs. */
-
-#include "common.h"
-#include "gpio.h"
-#include "hooks.h"
-
-#ifndef CONFIG_BLINK_LEDS
- #error The macro CONFIG_BLINK_LEDS must be specified to use BLINK.
-#endif
-
-static const enum gpio_signal leds[] = { CONFIG_BLINK_LEDS };
-
-BUILD_ASSERT(ARRAY_SIZE(leds) <= sizeof(int)*8, "Too many LEDs to drive.");
-BUILD_ASSERT(ARRAY_SIZE(leds) > 0, "Must have at least one LED to blink.");
-
-static void blink(void)
-{
- static int led_values;
-
- int i;
- for (i = 0; i < ARRAY_SIZE(leds); i++)
- gpio_set_level(leds[i], BIT(i) & led_values);
- led_values++;
-}
-DECLARE_HOOK(HOOK_TICK, blink, HOOK_PRIO_DEFAULT);
diff --git a/common/bluetooth_le.c b/common/bluetooth_le.c
deleted file mode 100644
index 2e68893223..0000000000
--- a/common/bluetooth_le.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/* Copyright 2016 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.
- */
-
-#include "bluetooth_le.h"
-#include "util.h"
-#include "console.h"
-
-#define CPRINTF(format, args...) cprintf(CC_BLUETOOTH_LE, format, ## args)
-
-/*
- * Convert from BLE Channel to frequency
- *
- * Bluetooth 4.1 Vol 6 pg 36 4.1 Table 1.1
- */
-
-#define CHAN_0_MHZ 2404
-#define CHAN_11_MHZ 2428
-#define CHAN_37_MHZ 2402
-#define CHAN_38_MHZ 2426
-#define CHAN_39_MHZ 2480
-
-int chan2freq(int channel)
-{
- int freq;
-
- ASSERT(channel < 40 && channel >= 0);
-
- switch (channel) {
- case 37: /* Advertising */
- freq = CHAN_37_MHZ;
- break;
- case 38: /* Advertising */
- freq = CHAN_38_MHZ;
- break;
- case 39: /* Advertising */
- freq = CHAN_39_MHZ;
- break;
- default:
- /* Data Channels */
- if (channel < 11)
- freq = channel * 2 + CHAN_0_MHZ;
- else
- freq = (channel - 11) * 2 + CHAN_11_MHZ;
- }
- return freq;
-}
-
-/* BLE 4.1 Vol 6 2.3.3.1 */
-
-void fill_remapping_table(struct remapping_table *rt, uint8_t map[5],
- int hop_increment)
-{
- int i;
-
- rt->num_used_channels = 0;
- rt->last_unmapped_channel = 0;
- rt->hop_increment = hop_increment;
-
- for (i = 0; i < 37; i++)
- if (map[i / 8] & (1 << (i % 8)))
- rt->remapping_index[rt->num_used_channels++] = i;
- memcpy(rt->map, map, sizeof(rt->map));
-}
-
-/* BLE 4.1 Vol 6 4.5.8 */
-uint8_t get_next_data_channel(struct remapping_table *rt)
-{
- rt->last_unmapped_channel =
- (rt->last_unmapped_channel + rt->hop_increment) % 37;
-
- /* Check if the channel is mapped */
- if (rt->map[rt->last_unmapped_channel / 8] &
- (1 << (rt->last_unmapped_channel % 8)))
- return rt->last_unmapped_channel;
- else
- return rt->remapping_index
- [rt->last_unmapped_channel % rt->num_used_channels];
-}
-
-/* BLE 4.1 Vol 3 Part C 11 */
-
-/* Pack advertising structures for sending */
-uint8_t *pack_adv(uint8_t *dest, int length, int type, const uint8_t *data)
-{
- /* Add the structure length */
- dest[0] = (uint8_t)length+1;
- /* Add the structure type */
- dest[1] = (uint8_t)type;
- /* Add the data */
- memcpy(&dest[2], data, length);
-
- /* Return a pointer to the next structure */
- return &dest[2+length];
-}
-
-uint8_t *pack_adv_int(uint8_t *dest, int length, int type, int data)
-{
- /* Add the structure length */
- dest[0] = (uint8_t)length+1;
- /* Add the structure type */
- dest[1] = (uint8_t)type;
- /* Add the data */
- memcpy(&dest[2], &data, length);
-
- /* Return a pointer to the next structure */
- return &dest[2+length];
-}
-
-uint8_t *pack_adv_addr(uint8_t *dest, uint64_t addr)
-{
- memcpy(&dest[0], &addr, BLUETOOTH_ADDR_OCTETS);
-
- /* Return a pointer to the next structure */
- return &dest[BLUETOOTH_ADDR_OCTETS];
-}
-
-/* Parse advertising structures that have been received */
-const uint8_t *unpack_adv(const uint8_t *src, int *length, int *type,
- const uint8_t **data)
-{
- /* Get the structure length */
- *length = *(src++);
- /* Get the structure type */
- *type = *(src++);
- /* Get the data */
- *data = src;
-
- /* Return a pointer to the next structure */
- return src + *length;
-}
-
-static void mem_dump(uint8_t *mem, int len)
-{
- int i;
- uint8_t value;
-
- for (i = 0; i < len; i++) {
- value = mem[i];
- if (i % 8 == 0)
- CPRINTF("\n%pP: %02x", &mem[i], value);
- else
- CPRINTF(" %02x", value);
- }
- CPRINTF("\n");
-}
-
-void dump_ble_addr(uint8_t *mem, char *name)
-{
- int i;
-
- for (i = 5; i > 0; i--)
- CPRINTF("%02x.", mem[i]);
- CPRINTF("%02x %s\n", mem[0], name);
-}
-
-void dump_ble_packet(struct ble_pdu *ble_p)
-{
- int curr_offs;
-
- if (ble_p->header_type_adv) {
- CPRINTF("BLE packet @ %pP: type %d, len %d, %s %s\n",
- ble_p, ble_p->header.adv.type, ble_p->header.adv.length,
- (ble_p->header.adv.txaddr ? " TXADDR" : ""),
- (ble_p->header.adv.rxaddr ? " RXADDR" : ""));
-
- curr_offs = 0;
-
- if (ble_p->header.adv.type ==
- BLE_ADV_HEADER_PDU_TYPE_SCAN_REQ) {
- dump_ble_addr(ble_p->payload, "ScanA");
- curr_offs += BLUETOOTH_ADDR_OCTETS;
- } else if (ble_p->header.adv.type ==
- BLE_ADV_HEADER_PDU_TYPE_CONNECT_REQ) {
- dump_ble_addr(ble_p->payload, "InitA");
- curr_offs += BLUETOOTH_ADDR_OCTETS;
- }
- /* All packets have AdvA */
- dump_ble_addr(ble_p->payload + curr_offs, "AdvA");
- curr_offs += BLUETOOTH_ADDR_OCTETS;
-
- if (ble_p->header.adv.type ==
- BLE_ADV_HEADER_PDU_TYPE_ADV_DIRECT_IND)
- dump_ble_addr(ble_p->payload + curr_offs, "InitA");
- else
- mem_dump(ble_p->payload + curr_offs,
- ble_p->header.adv.length - curr_offs);
- } else { /* Data PDUs */
- CPRINTF("BLE data packet @%pP: LLID %d,"
- " nesn %d, sn %d, md %d, length %d\n",
- ble_p, ble_p->header.data.llid, ble_p->header.data.nesn,
- ble_p->header.data.sn, ble_p->header.data.md,
- ble_p->header.data.length);
- mem_dump(ble_p->payload, ble_p->header.data.length);
- }
-}
-
diff --git a/common/body_detection.c b/common/body_detection.c
deleted file mode 100644
index 4fbc88e852..0000000000
--- a/common/body_detection.c
+++ /dev/null
@@ -1,256 +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.
- */
-
-#include "accelgyro.h"
-#include "body_detection.h"
-#include "console.h"
-#include "hwtimer.h"
-#include "lid_switch.h"
-#include "math_util.h"
-#include "motion_sense_fifo.h"
-#include "timer.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_ACCEL, outstr)
-#define CPRINTS(format, args...) cprints(CC_ACCEL, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args)
-
-static struct motion_sensor_t *body_sensor =
- &motion_sensors[CONFIG_BODY_DETECTION_SENSOR];
-
-static int window_size = CONFIG_BODY_DETECTION_MAX_WINDOW_SIZE;
-static uint64_t var_threshold_scaled, confidence_delta_scaled;
-static int stationary_timeframe;
-
-static int history_idx;
-static enum body_detect_states motion_state = BODY_DETECTION_OFF_BODY;
-
-static bool history_initialized;
-static bool body_detect_enable;
-STATIC_IF(CONFIG_ACCEL_SPOOF_MODE) bool spoof_enable;
-
-static struct body_detect_motion_data
-{
- int history[CONFIG_BODY_DETECTION_MAX_WINDOW_SIZE]; /* acceleration */
- int sum; /* sum(history) */
- uint64_t n2_variance; /* n^2 * var(history) */
-} data[2]; /* motion data for X-axis and Y-axis */
-
-/*
- * This function will update new variance and new sum according to incoming
- * value, previous value, previous sum and previous variance.
- * In order to prevent inaccuracy, we use integer to calculate instead of float
- *
- * n: window size
- * x: data in the old window
- * x': data in the new window
- * x_0: oldest value in the window, will be replaced by x_n
- * x_n: new coming value
- *
- * n^2 * var(x') = n^2 * var(x) + (x_n - x_0) *
- * (n * (x_n + x_0) - sum(x') - sum(x))
- */
-static void update_motion_data(struct body_detect_motion_data *x, int x_n)
-{
- const int n = window_size;
- const int x_0 = x->history[history_idx];
- const int sum_diff = x_n - x_0;
- const int new_sum = x->sum + sum_diff;
-
- x->n2_variance += sum_diff *
- ((int64_t)n * (x_n + x_0) - new_sum - x->sum);
- x->sum = new_sum;
- x->history[history_idx] = x_n;
-}
-
-/* Update motion data of X, Y with new sensor data. */
-static void update_motion_variance(void)
-{
- update_motion_data(&data[X], body_sensor->xyz[X]);
- update_motion_data(&data[Y], body_sensor->xyz[Y]);
- history_idx = (history_idx + 1 >= window_size) ? 0 : history_idx + 1;
-}
-
-/* return Var(X) + Var(Y) */
-static uint64_t get_motion_variance(void)
-{
- return (data[X].n2_variance + data[Y].n2_variance)
- / window_size / window_size;
-}
-
-static int calculate_motion_confidence(uint64_t var)
-{
- if (var < var_threshold_scaled - confidence_delta_scaled)
- return 0;
- if (var > var_threshold_scaled + confidence_delta_scaled)
- return 100;
- return 100 * (var - var_threshold_scaled + confidence_delta_scaled) /
- (2 * confidence_delta_scaled);
-}
-
-/* Change the motion state and commit the change to AP. */
-void body_detect_change_state(enum body_detect_states state, bool spoof)
-{
- if (IS_ENABLED(CONFIG_ACCEL_SPOOF_MODE) && spoof_enable && !spoof)
- return;
- if (IS_ENABLED(CONFIG_GESTURE_HOST_DETECTION)) {
- struct ec_response_motion_sensor_data vector = {
- .flags = MOTIONSENSE_SENSOR_FLAG_BYPASS_FIFO,
- .activity_data = {
- .activity = MOTIONSENSE_ACTIVITY_BODY_DETECTION,
- .state = state,
- },
- .sensor_num = MOTION_SENSE_ACTIVITY_SENSOR_ID,
- };
- motion_sense_fifo_stage_data(&vector, NULL, 0,
- __hw_clock_source_read());
- motion_sense_fifo_commit_data();
- }
- /* change the motion state */
- motion_state = state;
- if (state == BODY_DETECTION_ON_BODY) {
- /* reset time counting of stationary */
- stationary_timeframe = 0;
- }
- /* state changing log */
- CPRINTS("body_detect changed state to: %s body",
- motion_state ? "on" : "off");
-}
-
-enum body_detect_states body_detect_get_state(void)
-{
- return motion_state;
-}
-
-/* Determine window size for 1 second by sensor data rate. */
-static void determine_window_size(int odr)
-{
- window_size = odr / 1000;
- /* Normally, window_size should not exceed MAX_WINDOW_SIZE. */
- if (window_size > CONFIG_BODY_DETECTION_MAX_WINDOW_SIZE) {
- /* This will cause window size not enough for 1 second */
- CPRINTS("ODR exceeds CONFIG_BODY_DETECTION_MAX_WINDOW_SIZE");
- window_size = CONFIG_BODY_DETECTION_MAX_WINDOW_SIZE;
- }
-}
-
-/* Determine variance threshold scale by range and resolution. */
-static void determine_threshold_scale(int range, int resolution, int rms_noise)
-{
- /*
- * range: g
- * resolution: bits
- * data_1g: LSB/g
- * data_1g / 9800: LSB/(mm/s^2)
- * (data_1g / 9800)^2: (LSB^2)/(mm^2/s^4), which number of
- * var(sensor data) will represents 1 (mm^2/s^4)
- * rms_noise: ug
- * var_noise: mm^2/s^4
- */
- const int data_1g = BIT(resolution - 1) / range;
- const int multiplier = POW2(data_1g);
- const int divisor = POW2(9800);
- /*
- * We are measuring the var(X) + var(Y), so theoretically, the
- * var(noise) should be 2 * rms_noise^2. However, in most case, on a
- * very stationary plane, the average of var(noise) are less than 2 *
- * rms_noise^2. We can multiply the rms_noise^2 with the
- * CONFIG_BODY_DETECTION_VAR_NOISE_FACTOR / 100.
- */
- const int var_noise = POW2((uint64_t)rms_noise) *
- CONFIG_BODY_DETECTION_VAR_NOISE_FACTOR * POW2(98)
- / 100 / POW2(10000);
-
- var_threshold_scaled = (uint64_t)
- (CONFIG_BODY_DETECTION_VAR_THRESHOLD + var_noise) *
- multiplier / divisor;
- confidence_delta_scaled = (uint64_t)
- CONFIG_BODY_DETECTION_CONFIDENCE_DELTA *
- multiplier / divisor;
-}
-
-void body_detect_reset(void)
-{
- int odr = body_sensor->drv->get_data_rate(body_sensor);
- int resolution = body_sensor->drv->get_resolution(body_sensor);
- int rms_noise = body_sensor->drv->get_rms_noise(body_sensor);
-
- body_detect_change_state(BODY_DETECTION_ON_BODY, false);
- /*
- * The sensor is suspended since its ODR is 0,
- * there is no need to reset until sensor is up again
- */
- if (odr == 0)
- return;
- determine_window_size(odr);
- determine_threshold_scale(body_sensor->current_range,
- resolution, rms_noise);
- /* initialize motion data and state */
- memset(data, 0, sizeof(data));
- history_idx = 0;
- history_initialized = 0;
-}
-
-void body_detect(void)
-{
- uint64_t motion_var;
- int motion_confidence;
-
- if (!body_detect_enable)
- return;
-
- update_motion_variance();
- if (!history_initialized) {
- if (history_idx == window_size - 1)
- history_initialized = 1;
- return;
- }
-
- motion_var = get_motion_variance();
- motion_confidence = calculate_motion_confidence(motion_var);
- switch (motion_state) {
- case BODY_DETECTION_OFF_BODY:
- if (motion_confidence > CONFIG_BODY_DETECTION_ON_BODY_CON)
- body_detect_change_state(BODY_DETECTION_ON_BODY, false);
- break;
- case BODY_DETECTION_ON_BODY:
- stationary_timeframe += 1;
- /* confidence exceeds the limit, reset time counting */
- if (motion_confidence >= CONFIG_BODY_DETECTION_OFF_BODY_CON)
- stationary_timeframe = 0;
- /* if no motion for enough time, change state to off_body */
- if (stationary_timeframe >=
- CONFIG_BODY_DETECTION_STATIONARY_DURATION * window_size)
- body_detect_change_state(BODY_DETECTION_OFF_BODY,
- false);
- break;
- }
-}
-
-void body_detect_set_enable(int enable)
-{
- body_detect_enable = enable;
- body_detect_change_state(BODY_DETECTION_ON_BODY, false);
-}
-
-int body_detect_get_enable(void)
-{
- return body_detect_enable;
-}
-
-#ifdef CONFIG_ACCEL_SPOOF_MODE
-void body_detect_set_spoof(int enable)
-{
- spoof_enable = enable;
- /* After disabling spoof mode, commit current state. */
- if (!enable)
- body_detect_change_state(motion_state, false);
-}
-
-bool body_detect_get_spoof(void)
-{
- return spoof_enable;
-}
-#endif
diff --git a/common/btle_hci_controller.c b/common/btle_hci_controller.c
deleted file mode 100644
index cc5b872b19..0000000000
--- a/common/btle_hci_controller.c
+++ /dev/null
@@ -1,668 +0,0 @@
-/* Copyright 2016 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.
- */
-
-#include "btle_hci_int.h"
-#include "btle_hci2.h"
-#include "bluetooth_le_ll.h"
-#include "console.h"
-
-#ifdef CONFIG_BLUETOOTH_HCI_DEBUG
-
-#define CPUTS(outstr) cputs(CC_BLUETOOTH_HCI, outstr)
-#define CPRINTS(format, args...) cprints(CC_BLUETOOTH_HCI, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_BLUETOOTH_HCI, format, ## args)
-
-#else /* CONFIG_BLUETOOTH_HCI_DEBUG */
-
-#define CPUTS(outstr)
-#define CPRINTS(format, args...)
-#define CPRINTF(format, args...)
-
-#endif /* CONFIG_BLUETOOTH_HCI_DEBUG */
-
-static uint64_t hci_event_mask;
-static uint64_t hci_le_event_mask;
-
-#define MAX_MESSAGE 24
-
-#define STATUS (return_params[0])
-#define RPARAMS (&(return_params[1]))
-
-void hci_cmd(uint8_t *hciCmdbuf)
-{
- static struct hciCmdHdr *hdr;
- static uint8_t *params;
- static uint8_t return_params[32];
-
- uint8_t rparam_count = 1; /* Just status */
- uint16_t event = HCI_EVT_Command_Complete; /* default */
-
- STATUS = 0xff;
-
- hdr = (struct hciCmdHdr *)hciCmdbuf;
- params = hciCmdbuf + sizeof(struct hciCmdHdr);
-
- CPRINTF("opcode %x OGF %d OCF %d\n", hdr->opcode,
- CMD_GET_OGF(hdr->opcode), CMD_GET_OCF(hdr->opcode));
- if (hdr->paramLen) {
- int i;
-
- CPRINTF("paramLen %d\n", hdr->paramLen);
- for (i = 0; i < hdr->paramLen; i++)
- CPRINTF("%x ", params[i]);
- CPRINTF("\n");
- }
-
- switch (hdr->opcode) {
- case CMD_MAKE_OPCODE(HCI_OGF_Controller_and_Baseband,
- HCI_CMD_Reset):
- STATUS = ll_reset();
- break;
- case CMD_MAKE_OPCODE(HCI_OGF_Controller_and_Baseband,
- HCI_CMD_Set_Event_Mask):
- if (hdr->paramLen != sizeof(hci_event_mask))
- STATUS = HCI_ERR_Invalid_HCI_Command_Parameters;
- else
- STATUS = HCI_SUCCESS;
- memcpy(&hci_event_mask, params, sizeof(hci_event_mask));
- break;
- case CMD_MAKE_OPCODE(HCI_OGF_Controller_and_Baseband,
- HCI_CMD_Read_Transmit_Power_Level):
- case CMD_MAKE_OPCODE(HCI_OGF_Informational,
- HCI_CMD_Read_Local_Supported_Features):
- case CMD_MAKE_OPCODE(HCI_OGF_Informational,
- HCI_CMD_Read_Local_Supported_Commands):
- case CMD_MAKE_OPCODE(HCI_OGF_Informational,
- HCI_CMD_Read_Local_Version_Information):
- case CMD_MAKE_OPCODE(HCI_OGF_Informational,
- HCI_CMD_Read_BD_ADDR):
- case CMD_MAKE_OPCODE(HCI_OGF_Link_Control,
- HCI_CMD_Read_Remote_Version_Information):
- case CMD_MAKE_OPCODE(HCI_OGF_Status,
- HCI_CMD_Read_RSSI):
- event = 0;
- break;
-
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Set_Event_Mask):
- if (hdr->paramLen != sizeof(hci_le_event_mask))
- STATUS = HCI_ERR_Invalid_HCI_Command_Parameters;
- else
- STATUS = HCI_SUCCESS;
- memcpy(&hci_le_event_mask, params, sizeof(hci_le_event_mask));
- break;
-
- /* LE Information */
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Read_Buffer_Size):
- if (hdr->paramLen != 0)
- STATUS = HCI_ERR_Invalid_HCI_Command_Parameters;
- else
- STATUS = ll_read_buffer_size(RPARAMS);
- rparam_count = sizeof(struct hciCmplLeReadBufferSize);
- break;
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Read_Local_Supported_Features):
- if (hdr->paramLen != 0)
- STATUS = HCI_ERR_Invalid_HCI_Command_Parameters;
- else
- STATUS = ll_read_local_supported_features(RPARAMS);
- rparam_count =
- sizeof(struct hciCmplLeReadLocalSupportedFeatures);
- break;
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Read_Supported_States):
- if (hdr->paramLen != 0)
- STATUS = HCI_ERR_Invalid_HCI_Command_Parameters;
- else
- STATUS = ll_read_supported_states(RPARAMS);
- rparam_count = sizeof(struct hciCmplLeReadSupportedStates);
- break;
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Set_Host_Channel_Classification):
- if (hdr->paramLen !=
- sizeof(struct hciLeSetHostChannelClassification))
- STATUS = HCI_ERR_Invalid_HCI_Command_Parameters;
- else
- STATUS = ll_set_host_channel_classification(params);
- break;
-
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Set_Random_Address):
- if (hdr->paramLen != sizeof(struct hciLeSetRandomAddress))
- STATUS = HCI_ERR_Invalid_HCI_Command_Parameters;
- else
- STATUS = ll_set_random_address(params);
- break;
-
- /* Advertising */
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Set_Advertise_Enable):
- STATUS = ll_set_advertising_enable(params);
- break;
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Set_Advertising_Data):
- STATUS = ll_set_adv_data(params);
- break;
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Set_Adv_Params):
- if (hdr->paramLen != sizeof(struct hciLeSetAdvParams))
- STATUS = HCI_ERR_Invalid_HCI_Command_Parameters;
- else
- STATUS = ll_set_advertising_params(params);
- break;
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Read_Adv_Channel_TX_Power):
- STATUS = ll_read_tx_power();
- rparam_count = sizeof(struct hciCmplLeReadAdvChannelTxPower);
- break;
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Set_Scan_Response_Data):
- STATUS = ll_set_scan_response_data(params);
- break;
-
- /* Connections */
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Read_Remote_Used_Features):
- if (hdr->paramLen != sizeof(struct hciLeReadRemoteUsedFeatures))
- STATUS = HCI_ERR_Invalid_HCI_Command_Parameters;
- else
- STATUS = ll_read_remote_used_features(params);
- event = HCI_EVT_Command_Status;
- break;
- case CMD_MAKE_OPCODE(HCI_OGF_Link_Control,
- HCI_CMD_Disconnect):
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Connection_Update):
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Create_Connection):
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Create_Connection_Cancel):
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Read_Channel_Map):
- event = 0;
- break;
-
- /* Encryption */
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Encrypt):
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_LTK_Request_Reply):
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_LTK_Request_Negative_Reply):
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Rand):
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Start_Encryption):
- event = 0;
- break;
-
- /* Scanning */
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Set_Scan_Enable):
- if (hdr->paramLen != sizeof(struct hciLeSetScanEnable))
- STATUS = HCI_ERR_Invalid_HCI_Command_Parameters;
- else
- STATUS = ll_set_scan_enable(params);
- break;
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Set_Scan_Parameters):
- if (hdr->paramLen != sizeof(struct hciLeSetScanParams))
- STATUS = HCI_ERR_Invalid_HCI_Command_Parameters;
- else
- STATUS = ll_set_scan_params(params);
- break;
-
- /* Allow List */
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Clear_Allow_List):
- if (hdr->paramLen != 0)
- STATUS = HCI_ERR_Invalid_HCI_Command_Parameters;
- else
- STATUS = ll_clear_allow_list();
- break;
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Read_Allow_List_Size):
- if (hdr->paramLen != 0)
- STATUS = HCI_ERR_Invalid_HCI_Command_Parameters;
- else
- STATUS = ll_read_allow_list_size(RPARAMS);
- rparam_count = sizeof(struct hciCmplLeReadAllowListSize);
- break;
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Add_Device_To_Allow_List):
- if (hdr->paramLen != sizeof(struct hciLeAddDeviceToAllowList))
- STATUS = HCI_ERR_Invalid_HCI_Command_Parameters;
- else
- STATUS = ll_add_device_to_allow_list(params);
- break;
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Remove_Device_From_Allow_List):
- if (hdr->paramLen !=
- sizeof(struct hciLeRemoveDeviceFromAllowList))
- STATUS = HCI_ERR_Invalid_HCI_Command_Parameters;
- else
- STATUS = ll_remove_device_from_allow_list(params);
- break;
-
- /* RFPHY Testing Support */
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Receiver_Test):
- STATUS = ll_receiver_test(params);
- break;
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Transmitter_Test):
- STATUS = ll_transmitter_test(params);
- break;
- case CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Test_End):
- STATUS = ll_test_end(RPARAMS);
- rparam_count = sizeof(struct hciCmplLeTestEnd);
- break;
-
- default:
- STATUS = HCI_ERR_Unknown_HCI_Command;
- break;
- }
-
- hci_event(event, rparam_count, return_params);
-}
-
-void hci_acl_to_host(uint8_t *data, uint16_t hdr, uint16_t len)
-{
- int i;
-
- /* Enqueue hdr, len, len bytes of data */
- CPRINTF("Sending %d bytes of data from handle %d with PB=%x.\n",
- len, hdr & ACL_HDR_MASK_CONN_ID,
- hdr & ACL_HDR_MASK_PB);
- for (i = 0; i < len; i++)
- CPRINTF("0x%x, ", data[i]);
- CPRINTF("\n");
-}
-
-void hci_acl_from_host(uint8_t *hciAclbuf)
-{
- struct hciAclHdr *hdr = (struct hciAclHdr *)hciAclbuf;
- uint8_t *data = hciAclbuf + sizeof(struct hciAclHdr);
- int i;
-
- /* Send the data to the link layer */
- CPRINTF("Sending %d bytes of data to handle %d with PB=%x.\n",
- hdr->len, hdr->hdr & ACL_HDR_MASK_CONN_ID,
- hdr->hdr & ACL_HDR_MASK_PB);
- for (i = 0; i < hdr->len; i++)
- CPRINTF("0x%x, ", data[i]);
- CPRINTF("\n");
-}
-
-/*
- * Required Events
- *
- * HCI_EVT_Command_Complete
- * HCI_EVT_Command_Status
- * HCI_EVTLE_Advertising_Report
- * HCI_EVT_Disconnection_Complete
- * HCI_EVTLE_Connection_Complete
- * HCI_EVTLE_Connection_Update_Complete
- * HCI_EVTLE_Read_Remote_Used_Features_Complete
- * HCI_EVT_Number_Of_Completed_Packets
- * HCI_EVT_Read_Remote_Version_Complete
- * HCI_EVT_Encryption_Change
- * HCI_EVT_Encryption_Key_Refresh_Complete
- * HCI_EVTLE_Long_Term_Key_Request
- */
-void hci_event(uint8_t event_code, uint8_t len, uint8_t *params)
-{
- int i;
-
- /* Copy it to the queue. */
- CPRINTF("Event 0x%x len %d\n", event_code, len);
- for (i = 0; i < len; i++)
- CPRINTF("%x ", params[i]);
- CPRINTF("\n");
-}
-
-#ifdef CONFIG_BLUETOOTH_HCI_DEBUG
-
-/*
- * LE_Set_Advertising_Data
- * hcitool lcmd 0x2008 19 0x42410907 0x46454443 0x3c11903 0x3050102 0x181203
- * hcitool cmd 8 8 7 9 41 42 43 44 45 46 3 19 c1 3 2 1 5 3 3 12 18
- *
- * hcitool lcmd 0x2008 18 0x42410906 0x03454443 0x203c119 0x3030501 0x1812
- * hcitool cmd 8 8 6 9 41 42 43 44 45 3 19 c1 3 2 1 5 3 3 12 18
- */
-uint8_t adv0[19] = {0x07, 0x09, 'A', 'B', 'C', 'D', 'E', 'F', /* Name */
- 0x03, 0x19, 0xc1, 0x03, /* Keyboard */
- 0x02, 0x01, 0x05, /* Flags */
- 0x03, 0x03, 0x12, 0x18}; /* UUID */
-
-uint8_t adv1[18] = {0x06, 0x09, 'A', 'B', 'C', 'D', 'E', /* Name */
- 0x02, 0x01, 0x05, /* Flags */
- 0x03, 0x19, 0xc1, 0x03, /* Keyboard */
- 0x03, 0x03, 0x12, 0x18}; /* UUID */
-
-uint8_t *adverts[] = {adv0, adv1};
-uint8_t adv_lengths[] = {sizeof(adv0), sizeof(adv1)};
-
-uint8_t scan0[4] = {0x03, 0x08, 'A', 'B'}; /* Short Name */
-
-uint8_t scan1[] = {}; /* Empty */
-
-uint8_t *scans[] = {scan0, scan1};
-uint8_t scan_lengths[] = {sizeof(scan0), sizeof(scan1)};
-
-/*
- * LE_Set_Adv_Params
- * hcitool lcmd 0x2006 15 0x010000f0 0xb0010100 0xb4b3b2b1 0x0007c5
- * hcitool cmd 8 6 f0 0 0 1 0 1 1 b0 b1 b2 b3 b4 c5 7 0
- */
-uint8_t adv_param0[15] = {
- 0xf0, 0x00, /* IntervalMin */
- 0x00, 0x01, /* IntervalMax */
- 0x00, /* Adv Type */
- 0x01, /* Use Random Addr */
- 0x01, /* Direct Random */
- 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xc5, /* Direct Addr */
- 0x07, /* Channel Map */
- 0x00}; /* Filter Policy */
-
-uint8_t adv_param1[15] = {
- 0xf0, 0x00, /* IntervalMin */
- 0x00, 0x01, /* IntervalMax */
- 0x02, /* Adv Type */
- 0x01, /* Use Random Addr */
- 0x01, /* Direct Random */
- 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xc5, /* Direct Addr */
- 0x07, /* Channel Map */
- 0x00}; /* Filter Policy */
-
-uint8_t *adv_params[] = {adv_param0, adv_param1};
-
-/*
- * LE Information
- *
- * LE Read Buffer Size
- * hcitool cmd 8 2
- *
- * LE_Read_Local_Supported_Features
- * hcitool cmd 8 3
- *
- * LE_Read_Supported_States
- * hcitool cmd 8 1c
- *
- * LE_Set_Host_Channel_Classification
- * hcitool cmd 8 14 0 1 2 3 4
- * hcitool cmd 8 14 ff ff 02 ff 1f
- */
-
-/*
- * Scan commands:
- *
- * Set Scan Parameters:
- * hcitool cmd 8 B 0 10 0 10 0 0 0 (passive 10 10 public all)
- * hcitool lcmd 0x200B 7 0x10001000 0x0000 (passive 10 10 public all)
- *
- * hcitool cmd 8 B 1 30 0 20 0 1 1 (active 30 20 rand white)
- * hcitool lcmd 0x200B 7 0x20003001 0x0101 (active 30 20 rand white)
- *
- * Set Scan Enable:
- * hcitool cmd 8 C 0 0 (disabled)
- * hcitool cmd 8 C 1 0 (enabled no_filtering)
- * hcitool cmd 8 C 1 1 (enabled filter_duplicates)
- *
- */
-
-/* Allow list commands:
- *
- * Read allow list size
- * hcitool cmd 8 F
- *
- * Clear allow list
- * hcitool cmd 8 10
- *
- * Add device to allow list (Public C5A4A3A2A1A0)
- * hcitool cmd 8 11 0 a0 a1 a2 a3 a4 c5
- * hcitool lcmd 0x2011 7 0xA2A1A000 0xC5A4A3
- *
- * Add device to allow list (Random C5B4B3B2B1B0)
- * hcitool cmd 8 11 1 b0 b1 b2 b4 b5 c5
- * hcitool lcmd 0x2011 7 0xB2B1B001 0xC5B4B3
- *
- * Remove device from allow list (Public C5A4A3A2A1A0)
- * hcitool cmd 8 12 0 a0 a1 a2 a3 a4 c5
- * hcitool lcmd 0x2012 7 0xA2A1A000 0xC5A4A3
- *
- * Remove device from allow list (Random C5B4B3B2B1B0)
- * hcitool cmd 8 12 1 b0 b1 b2 b4 b5 c5
- * hcitool lcmd 0x2012 7 0xB2B1B001 0xC5B4B3
- *
- * Tested by checking dumping the allow list and checking its size when:
- * - adding devices
- * - removing devices
- * - removing non-existent devices
- * - adding more than 8 devices
- *
- */
-
-/*
- * Test commands:
- *
- * Rx Test channel 37
- * hcitool cmd 8 1D 25
- *
- * Tx Test channel 37 20 bytes type 2
- * hcitool cmd 8 1e 25 14 2
- *
- * Test end
- * hcitool cmd 8 1f
- */
-
-static uint8_t hci_buf[200];
-
-#define MAX_BLE_HCI_PARAMS 8
-static uint32_t param[MAX_BLE_HCI_PARAMS];
-
-static int command_ble_hci_cmd(int argc, char **argv)
-{
- static struct hciCmdHdr header;
- int length, opcode, i;
- char *e;
-
- if (argc < 3 || argc > MAX_BLE_HCI_PARAMS + 3)
- return EC_ERROR_PARAM_COUNT;
-
- opcode = strtoi(argv[1], &e, 0);
- if (*e || opcode < 0 || opcode > 0xffff)
- return EC_ERROR_PARAM1;
-
- length = strtoi(argv[2], &e, 0);
- if (*e || length < 0 || length > 32)
- return EC_ERROR_PARAM2;
-
- if ((length + 3) / 4 != argc - 3) {
- CPRINTF("Remember to pass HCI params in 32-bit chunks.\n");
- return EC_ERROR_PARAM_COUNT;
- }
-
- for (i = 3; i < argc; i++) {
- param[i-3] = strtoi(argv[i], &e, 0);
- if (*e)
- return EC_ERROR_PARAM3 + i;
- }
-
- header.opcode = opcode;
- header.paramLen = length;
-
- memcpy(hci_buf, &header, sizeof(struct hciCmdHdr));
- memcpy(hci_buf + sizeof(struct hciCmdHdr),
- param, length);
-
- hci_cmd(hci_buf);
-
- CPRINTS("hci cmd @%pP", hci_buf);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(ble_hci_cmd, command_ble_hci_cmd,
- "opcode len uint32 uint32 uint32... (little endian)",
- "Send an hci command of length len");
-
-static int command_hcitool(int argc, char **argv)
-{
- static struct hciCmdHdr header;
- int i, ogf, ocf;
- char *e;
-
- if (argc < 4 || argc > MAX_BLE_HCI_PARAMS + 3)
- return EC_ERROR_PARAM_COUNT;
-
- if (argv[1][0] == 'l') /* strcmp lcmd */
- return command_ble_hci_cmd(argc-1, &argv[1]);
-
- ogf = strtoi(argv[2], &e, 16);
- if (*e)
- return EC_ERROR_PARAM2;
-
- ocf = strtoi(argv[3], &e, 16);
- if (*e)
- return EC_ERROR_PARAM3;
-
- header.opcode = CMD_MAKE_OPCODE(ogf, ocf);
- header.paramLen = argc-4;
- memcpy(hci_buf, &header, sizeof(struct hciCmdHdr));
-
- for (i = 4; i < argc; i++) {
- hci_buf[i - 4 + 3] = strtoi(argv[i], &e, 16);
- if (*e)
- return EC_ERROR_PARAM4 + i;
- }
-
- hci_cmd(hci_buf);
-
- CPRINTS("hci cmd @%pP", hci_buf);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(hcitool, command_hcitool,
- "cmd ogf ocf b0 b1 b2 b3... or lcmd opcode len uint32.. (little endian)",
- "Send an hci command of length len");
-
-static int command_ble_hci_acl(int argc, char **argv)
-{
- static struct hciAclHdr header;
- int length, hdr, i;
- char *e;
-
- if (argc < 3 || argc > MAX_BLE_HCI_PARAMS + 3)
- return EC_ERROR_PARAM_COUNT;
-
- hdr = strtoi(argv[1], &e, 0);
- if (*e || hdr < 0 || hdr > 0xffff)
- return EC_ERROR_PARAM1;
-
- length = strtoi(argv[2], &e, 0);
- if (*e || length < 0 || length > 32)
- return EC_ERROR_PARAM2;
-
- if ((length + 3) / 4 != argc - 3) {
- CPRINTF("Remember to pass HCI params in 32-bit chunks.\n");
- return EC_ERROR_PARAM_COUNT;
- }
-
- for (i = 3; i < argc; i++) {
- param[i-3] = strtoi(argv[i], &e, 0);
- if (*e)
- return EC_ERROR_PARAM3 + i;
- }
-
- header.hdr = hdr;
- header.len = length;
-
- memcpy(hci_buf, &header, sizeof(struct hciCmdHdr));
- memcpy(hci_buf + sizeof(struct hciCmdHdr),
- param, length);
-
- hci_cmd(hci_buf);
-
- CPRINTS("hci acl @%pP", hci_buf);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(ble_hci_acl, command_ble_hci_acl,
- "hdr len uint32 uint32 uint32... (little endian)",
- "Send hci acl data of length len");
-
-static int command_ble_hci_adv(int argc, char **argv)
-{
- static struct hciCmdHdr header;
- int adv, p = 0, scan_rsp = 0;
- char *e;
-
- if (argc < 2 || argc > 4)
- return EC_ERROR_PARAM_COUNT;
-
- adv = strtoi(argv[1], &e, 0);
- if (*e || adv < 0 || adv > sizeof(adverts))
- return EC_ERROR_PARAM1;
-
- if (argc > 2) {
- p = strtoi(argv[2], &e, 0);
- if (*e || p < 0 || p > sizeof(adv_params))
- return EC_ERROR_PARAM2;
- }
-
- if (argc > 3) {
- scan_rsp = strtoi(argv[3], &e, 0);
- if (*e || scan_rsp < 0 || scan_rsp > sizeof(scans))
- return EC_ERROR_PARAM3;
- }
-
- header.opcode = CMD_MAKE_OPCODE(HCI_OGF_LE, HCI_CMD_LE_Set_Adv_Params);
- header.paramLen = sizeof(struct hciLeSetAdvParams);
-
- memcpy(hci_buf, &header, sizeof(struct hciCmdHdr));
- memcpy(hci_buf + sizeof(struct hciCmdHdr),
- adv_params[p], header.paramLen);
-
- hci_cmd(hci_buf);
-
- header.opcode = CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Set_Advertising_Data);
- header.paramLen = adv_lengths[adv];
-
- memcpy(hci_buf, &header, sizeof(struct hciCmdHdr));
- memcpy(hci_buf + sizeof(struct hciCmdHdr),
- adverts[adv], header.paramLen);
-
- hci_cmd(hci_buf);
-
- header.opcode = CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Set_Scan_Response_Data);
- header.paramLen = scan_lengths[scan_rsp];
-
- memcpy(hci_buf, &header, sizeof(struct hciCmdHdr));
- memcpy(hci_buf + sizeof(struct hciCmdHdr),
- scans[scan_rsp], header.paramLen);
-
- hci_cmd(hci_buf);
-
- header.opcode = CMD_MAKE_OPCODE(HCI_OGF_LE,
- HCI_CMD_LE_Set_Advertise_Enable);
- header.paramLen = sizeof(struct hciLeSetAdvEnable);
-
- memcpy(hci_buf, &header, sizeof(struct hciCmdHdr));
- hci_buf[sizeof(struct hciCmdHdr)] = 1;
-
- hci_cmd(hci_buf);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(ble_hci_adv, command_ble_hci_adv,
- "adv [params=0] [scan_rsp=0]",
- "Use pre-defined parameters to start advertising");
-
-#endif /* CONFIG_BLUETOOTH_HCI_DEBUG */
diff --git a/common/btle_ll.c b/common/btle_ll.c
deleted file mode 100644
index 20ede4d4a0..0000000000
--- a/common/btle_ll.c
+++ /dev/null
@@ -1,861 +0,0 @@
-/* Copyright 2016 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.
- */
-
-#include "bluetooth_le_ll.h"
-#include "bluetooth_le.h"
-#include "btle_hci_int.h"
-#include "util.h"
-#include "console.h"
-#include "radio.h"
-#include "radio_test.h"
-#include "task.h"
-#include "timer.h"
-
-#ifdef CONFIG_BLUETOOTH_LL_DEBUG
-
-#define CPUTS(outstr) cputs(CC_BLUETOOTH_LL, outstr)
-#define CPRINTS(format, args...) cprints(CC_BLUETOOTH_LL, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_BLUETOOTH_LL, format, ## args)
-
-#else /* CONFIG_BLUETOOTH_LL_DEBUG */
-
-#define CPUTS(outstr)
-#define CPRINTS(format, args...)
-#define CPRINTF(format, args...)
-
-#endif /* CONFIG_BLUETOOTH_LL_DEBUG */
-
-/* Link Layer */
-
-enum ll_state_t ll_state = UNINITIALIZED;
-
-static struct hciLeSetAdvParams ll_adv_params;
-static struct hciLeSetScanParams ll_scan_params;
-static int ll_adv_interval_us;
-static int ll_adv_timeout_us;
-
-static struct ble_pdu ll_adv_pdu;
-static struct ble_pdu ll_scan_rsp_pdu;
-static struct ble_pdu tx_packet_1;
-static struct ble_pdu *packet_tb_sent;
-static struct ble_connection_params conn_params;
-static int connection_initialized;
-static struct remapping_table remap_table;
-
-static uint64_t receive_time, last_receive_time;
-static uint8_t num_consecutive_failures;
-
-static uint32_t tx_end, tx_rsp_end, time_of_connect_req;
-struct ble_pdu ll_rcv_packet;
-static uint32_t ll_conn_events;
-static uint32_t errors_recovered;
-
-int ll_power;
-uint8_t is_first_data_packet;
-
-static uint64_t ll_random_address = 0xC5BADBADBAD1; /* Uninitialized */
-static uint64_t ll_public_address = 0xC5BADBADBADF; /* Uninitialized */
-static uint8_t ll_channel_map[5] = {0xff, 0xff, 0xff, 0xff, 0x1f};
-
-static uint8_t ll_filter_duplicates;
-
-int ll_pseudo_rand(int max_plus_one)
-{
- static uint32_t lfsr = 0x55555;
- int lsb = lfsr & 1;
-
- lfsr = lfsr >> 1;
- if (lsb)
- lfsr ^= 0x80020003; /* Bits 32, 22, 2, 1 */
- return lfsr % max_plus_one;
-}
-
-uint8_t ll_set_tx_power(uint8_t *params)
-{
- /* Add checking */
- ll_power = params[0];
- return HCI_SUCCESS;
-}
-
-uint8_t ll_read_tx_power(void)
-{
- return ll_power;
-}
-
-/* LE Information */
-uint8_t ll_read_buffer_size(uint8_t *return_params)
-{
- return_params[0] = LL_MAX_DATA_PACKET_LENGTH & 0xff;
- return_params[1] = (LL_MAX_DATA_PACKET_LENGTH >> 8) & 0xff;
- return_params[2] = LL_MAX_DATA_PACKETS;
- return HCI_SUCCESS;
-}
-
-uint8_t ll_read_local_supported_features(uint8_t *return_params)
-{
- uint64_t supported_features = LL_SUPPORTED_FEATURES;
-
- memcpy(return_params, &supported_features, sizeof(supported_features));
- return HCI_SUCCESS;
-}
-
-uint8_t ll_read_supported_states(uint8_t *return_params)
-{
- uint64_t supported_states = LL_SUPPORTED_STATES;
-
- memcpy(return_params, &supported_states, sizeof(supported_states));
- return HCI_SUCCESS;
-}
-
-uint8_t ll_set_host_channel_classification(uint8_t *params)
-{
- memcpy(ll_channel_map, params, sizeof(ll_channel_map));
- return HCI_SUCCESS;
-}
-
-/* Advertising */
-uint8_t ll_set_scan_response_data(uint8_t *params)
-{
- if (params[0] > BLE_MAX_ADV_PAYLOAD_OCTETS)
- return HCI_ERR_Invalid_HCI_Command_Parameters;
-
- if (ll_state == ADVERTISING)
- return HCI_ERR_Controller_Busy;
-
- memcpy(&ll_scan_rsp_pdu.payload[BLUETOOTH_ADDR_OCTETS], &params[1],
- params[0]);
- ll_scan_rsp_pdu.header.adv.length = params[0] + BLUETOOTH_ADDR_OCTETS;
-
- return HCI_SUCCESS;
-}
-
-uint8_t ll_set_adv_data(uint8_t *params)
-{
- if (params[0] > BLE_MAX_ADV_PAYLOAD_OCTETS)
- return HCI_ERR_Invalid_HCI_Command_Parameters;
-
- if (ll_state == ADVERTISING)
- return HCI_ERR_Controller_Busy;
-
- /* Skip the address */
- memcpy(&ll_adv_pdu.payload[BLUETOOTH_ADDR_OCTETS], &params[1],
- params[0]);
- ll_adv_pdu.header.adv.length = params[0] + BLUETOOTH_ADDR_OCTETS;
-
- return HCI_SUCCESS;
-}
-
-uint8_t ll_reset(void)
-{
- ll_state = UNINITIALIZED;
- radio_disable();
-
- ble_radio_clear_allow_list();
-
- return HCI_SUCCESS;
-}
-
-static uint8_t ll_state_change_request(enum ll_state_t next_state)
-{
- /* Initialize the radio if it hasn't been initialized */
- if (ll_state == UNINITIALIZED) {
- if (ble_radio_init(BLE_ADV_ACCESS_ADDRESS, BLE_ADV_CRCINIT)
- != EC_SUCCESS)
- return HCI_ERR_Hardware_Failure;
- ll_state = STANDBY;
- }
-
- /* Only change states when the link layer is in STANDBY */
- if (next_state != STANDBY && ll_state != STANDBY)
- return HCI_ERR_Controller_Busy;
-
- ll_state = next_state;
-
- return HCI_SUCCESS;
-}
-
-uint8_t ll_set_advertising_enable(uint8_t *params)
-{
- uint8_t rv;
-
- if (params[0]) {
- rv = ll_state_change_request(ADVERTISING);
- if (rv == HCI_SUCCESS)
- task_wake(TASK_ID_BLE_LL);
- } else {
- rv = ll_state_change_request(STANDBY);
- }
-
- return rv;
-}
-
-uint8_t ll_set_scan_enable(uint8_t *params)
-{
- uint8_t rv;
-
- if (params[0]) {
- ll_filter_duplicates = params[1];
- rv = ll_state_change_request(SCANNING);
- if (rv == HCI_SUCCESS)
- task_wake(TASK_ID_BLE_LL);
- } else {
- rv = ll_state_change_request(STANDBY);
- }
-
- return HCI_SUCCESS;
-}
-
-void set_empty_data_packet(struct ble_pdu *pdu)
-{
- /* LLID == 1 means incomplete or empty data packet */
- pdu->header.data.llid = 1;
- pdu->header.data.nesn = 1;
- pdu->header.data.sn = 0;
- pdu->header.data.md = 0;
- pdu->header.data.length = 0;
- pdu->header_type_adv = 0;
-}
-
-/* Connection state */
-
-/**
- * This function serves to take data from a CONNECT_REQ packet and copy it
- * into a struct, conn_params, which defines the parameter of the connection.
- * It also fills a remapping table, another essential element of the link
- * layer connection.
- */
-uint8_t initialize_connection(void)
-{
- int cur_offset = 0, i = 0;
- uint8_t final_octet = 0;
- uint8_t remap_arr[5];
- uint8_t *payload_start = (uint8_t *)(ll_rcv_packet.payload);
-
- num_consecutive_failures = 0;
-
- /* Copy data into the appropriate portions of memory */
- memcpy((uint8_t *)&(conn_params.init_a),
- payload_start, CONNECT_REQ_INITA_LEN);
- cur_offset += CONNECT_REQ_INITA_LEN;
-
- memcpy((uint8_t *)&(conn_params.adv_a),
- payload_start+cur_offset, CONNECT_REQ_ADVA_LEN);
- cur_offset += CONNECT_REQ_ADVA_LEN;
-
- memcpy(&(conn_params.access_addr),
- payload_start+cur_offset, CONNECT_REQ_ACCESS_ADDR_LEN);
- cur_offset += CONNECT_REQ_ACCESS_ADDR_LEN;
-
- conn_params.crc_init_val = 0;
- memcpy(&(conn_params.crc_init_val),
- payload_start+cur_offset, CONNECT_REQ_CRC_INIT_VAL_LEN);
- cur_offset += CONNECT_REQ_CRC_INIT_VAL_LEN;
-
- memcpy(&(conn_params.win_size),
- payload_start+cur_offset, CONNECT_REQ_WIN_SIZE_LEN);
- cur_offset += CONNECT_REQ_WIN_SIZE_LEN;
-
- memcpy(&(conn_params.win_offset),
- payload_start+cur_offset, CONNECT_REQ_WIN_OFFSET_LEN);
- cur_offset += CONNECT_REQ_WIN_OFFSET_LEN;
-
- memcpy(&(conn_params.interval),
- payload_start+cur_offset, CONNECT_REQ_INTERVAL_LEN);
- cur_offset += CONNECT_REQ_INTERVAL_LEN;
-
- memcpy(&(conn_params.latency),
- payload_start+cur_offset, CONNECT_REQ_LATENCY_LEN);
- cur_offset += CONNECT_REQ_LATENCY_LEN;
-
- memcpy(&(conn_params.timeout),
- payload_start+cur_offset, CONNECT_REQ_TIMEOUT_LEN);
- cur_offset += CONNECT_REQ_TIMEOUT_LEN;
-
- conn_params.channel_map = 0;
- memcpy(&(conn_params.channel_map),
- payload_start+cur_offset, CONNECT_REQ_CHANNEL_MAP_LEN);
- cur_offset += CONNECT_REQ_CHANNEL_MAP_LEN;
-
- memcpy(&final_octet, payload_start+cur_offset,
- CONNECT_REQ_HOP_INCREMENT_AND_SCA_LEN);
-
- /* last 5 bits of final_octet: */
- conn_params.hop_increment = final_octet & 0x1f;
- /* first 3 bits of final_octet: */
- conn_params.sleep_clock_accuracy = (final_octet & 0xe0) >> 5;
-
- /* Set up channel mapping table */
- for (i = 0; i < 5; ++i)
- remap_arr[i] = *(((uint8_t *)&(conn_params.channel_map))+i);
- fill_remapping_table(&remap_table, remap_arr,
- conn_params.hop_increment);
-
- /* Calculate transmission window parameters */
- conn_params.transmitWindowSize = conn_params.win_size * 1250;
- conn_params.transmitWindowOffset = conn_params.win_offset * 1250;
- conn_params.connInterval = conn_params.interval * 1250;
- /* The following two lines convert ms -> microseconds */
- conn_params.connLatency = 1000 * conn_params.latency;
- conn_params.connSupervisionTimeout = 10000 * conn_params.timeout;
- /* All these times are in microseconds! */
-
- /* Check for common transmission errors */
- if (conn_params.hop_increment < 5 || conn_params.hop_increment > 16) {
- for (i = 0; i < 5; ++i)
- CPRINTF("ERROR!! ILLEGAL HOP_INCREMENT!!\n");
- return HCI_ERR_Invalid_LMP_Parameters;
- }
-
- is_first_data_packet = 1;
- return HCI_SUCCESS;
-}
-
-/* Allow List */
-uint8_t ll_clear_allow_list(void)
-{
- if (ble_radio_clear_allow_list() == EC_SUCCESS)
- return HCI_SUCCESS;
- else
- return HCI_ERR_Hardware_Failure;
-}
-
-uint8_t ll_read_allow_list_size(uint8_t *return_params)
-{
- if (ble_radio_read_allow_list_size(return_params) == EC_SUCCESS)
- return HCI_SUCCESS;
- else
- return HCI_ERR_Hardware_Failure;
-}
-
-uint8_t ll_add_device_to_allow_list(uint8_t *params)
-{
- if (ble_radio_add_device_to_allow_list(&params[1], params[0]) ==
- EC_SUCCESS)
- return HCI_SUCCESS;
- else
- return HCI_ERR_Host_Rejected_Due_To_Limited_Resources;
-}
-
-uint8_t ll_remove_device_from_allow_list(uint8_t *params)
-{
- if (ble_radio_remove_device_from_allow_list(&params[1], params[0]) ==
- EC_SUCCESS)
- return HCI_SUCCESS;
- else
- return HCI_ERR_Hardware_Failure;
-}
-
-/* Connections */
-uint8_t ll_read_remote_used_features(uint8_t *params)
-{
- uint16_t handle = params[0] | (((uint16_t)params[1]) << 8);
-
- CPRINTS("Read remote used features for handle %d", handle);
- /* Check handle */
- return HCI_SUCCESS;
-}
-
-/* RF PHY Testing */
-static int ll_test_packets;
-
-uint8_t ll_receiver_test(uint8_t *params)
-{
- int rv;
-
- ll_test_packets = 0;
-
- /* See if the link layer is busy */
- rv = ll_state_change_request(TEST_RX);
- if (rv)
- return rv;
-
- rv = ble_test_rx_init(params[0]);
- if (rv)
- return rv;
-
- CPRINTS("Start Rx test");
- task_wake(TASK_ID_BLE_LL);
-
- return HCI_SUCCESS;
-}
-
-uint8_t ll_transmitter_test(uint8_t *params)
-{
- int rv;
-
- ll_test_packets = 0;
-
- /* See if the link layer is busy */
- rv = ll_state_change_request(TEST_TX);
- if (rv)
- return rv;
-
- rv = ble_test_tx_init(params[0], params[1], params[2]);
- if (rv)
- return rv;
-
- CPRINTS("Start Tx test");
- task_wake(TASK_ID_BLE_LL);
-
- return HCI_SUCCESS;
-}
-
-uint8_t ll_test_end(uint8_t *return_params)
-{
- CPRINTS("End (%d packets)", ll_test_packets);
-
- ble_test_stop();
-
- if (ll_state == TEST_RX) {
- return_params[0] = ll_test_packets & 0xff;
- return_params[1] = (ll_test_packets >> 8);
- ll_test_packets = 0;
- } else {
- return_params[0] = 0;
- return_params[1] = 0;
- ll_test_packets = 0;
- }
- return ll_reset();
-}
-
-uint8_t ll_set_random_address(uint8_t *params)
-{
- /* No checking. The host should know the rules. */
- memcpy(&ll_random_address, params,
- sizeof(struct hciLeSetRandomAddress));
- return HCI_SUCCESS;
-}
-
-uint8_t ll_set_scan_params(uint8_t *params)
-{
- if (ll_state == SCANNING)
- return HCI_ERR_Controller_Busy;
-
- memcpy(&ll_scan_params, params, sizeof(struct hciLeSetScanParams));
-
- return HCI_SUCCESS;
-}
-
-uint8_t ll_set_advertising_params(uint8_t *params)
-{
- if (ll_state == ADVERTISING)
- return HCI_ERR_Controller_Busy;
-
- memcpy(&ll_adv_params, params, sizeof(struct hciLeSetAdvParams));
-
- switch (ll_adv_params.advType) {
- case BLE_ADV_HEADER_PDU_TYPE_ADV_NONCONN_IND:
- case BLE_ADV_HEADER_PDU_TYPE_ADV_SCAN_IND:
- if (ll_adv_params.advIntervalMin <
- (100000 / LL_ADV_INTERVAL_UNIT_US)) /* 100ms */
- return HCI_ERR_Invalid_HCI_Command_Parameters;
- /* Fall through */
- case BLE_ADV_HEADER_PDU_TYPE_ADV_IND:
- if (ll_adv_params.advIntervalMin > ll_adv_params.advIntervalMax)
- return HCI_ERR_Invalid_HCI_Command_Parameters;
- if (ll_adv_params.advIntervalMin <
- (20000 / LL_ADV_INTERVAL_UNIT_US) || /* 20ms */
- ll_adv_params.advIntervalMax >
- (10240000 / LL_ADV_INTERVAL_UNIT_US)) /* 10.24s */
- return HCI_ERR_Invalid_HCI_Command_Parameters;
- ll_adv_interval_us = (((ll_adv_params.advIntervalMin +
- ll_adv_params.advIntervalMax) / 2) *
- LL_ADV_INTERVAL_UNIT_US);
- /* Don't time out */
- ll_adv_timeout_us = -1;
- break;
- case BLE_ADV_HEADER_PDU_TYPE_ADV_DIRECT_IND:
- ll_adv_interval_us = LL_ADV_DIRECT_INTERVAL_US;
- ll_adv_timeout_us = LL_ADV_DIRECT_TIMEOUT_US;
- break;
- default:
- return HCI_ERR_Invalid_HCI_Command_Parameters;
- }
-
- /* Initialize the ADV PDU */
- ll_adv_pdu.header_type_adv = 1;
- ll_adv_pdu.header.adv.type = ll_adv_params.advType;
- ll_adv_pdu.header.adv.txaddr = ll_adv_params.useRandomAddress;
-
- if (ll_adv_params.useRandomAddress)
- memcpy(ll_adv_pdu.payload, &ll_random_address,
- BLUETOOTH_ADDR_OCTETS);
- else
- memcpy(ll_adv_pdu.payload, &ll_public_address,
- BLUETOOTH_ADDR_OCTETS);
-
- if (ll_adv_params.advType == BLE_ADV_HEADER_PDU_TYPE_ADV_DIRECT_IND) {
- ll_adv_pdu.header.adv.rxaddr =
- ll_adv_params.directRandomAddress;
- memcpy(&ll_adv_pdu.payload[BLUETOOTH_ADDR_OCTETS],
- ll_adv_params.directAddr,
- sizeof(ll_adv_params.directAddr));
- ll_adv_pdu.header.adv.length = 12;
- } else {
- ll_adv_pdu.header.adv.rxaddr = 0;
- }
-
- /* All other types get data from SetAdvertisingData */
-
- /* Initialize the Scan Rsp PDU */
- ll_scan_rsp_pdu.header_type_adv = 1;
- ll_scan_rsp_pdu.header.adv.type = BLE_ADV_HEADER_PDU_TYPE_SCAN_RSP;
- ll_scan_rsp_pdu.header.adv.txaddr = ll_adv_params.useRandomAddress;
-
- if (ll_adv_params.useRandomAddress)
- memcpy(ll_scan_rsp_pdu.payload, &ll_random_address,
- BLUETOOTH_ADDR_OCTETS);
- else
- memcpy(ll_scan_rsp_pdu.payload, &ll_public_address,
- BLUETOOTH_ADDR_OCTETS);
-
- ll_scan_rsp_pdu.header.adv.rxaddr = 0;
-
- return HCI_SUCCESS;
-}
-
-static uint32_t tx_end, rsp_end, tx_rsp_end;
-struct ble_pdu ll_rcv_packet;
-
-/**
- * Advertises packet that has already been generated on given channel.
- *
- * This function also processes any incoming scan requests.
- *
- * @param chan The channel on which to advertise.
- * @returns EC_SUCCESS on packet reception, otherwise error.
- */
-int ble_ll_adv(int chan)
-{
- int rv;
-
- ble_radio_init(BLE_ADV_ACCESS_ADDRESS, BLE_ADV_CRCINIT);
-
- /* Change channel */
- NRF51_RADIO_FREQUENCY = NRF51_RADIO_FREQUENCY_VAL(chan2freq(chan));
- NRF51_RADIO_DATAWHITEIV = chan;
-
- ble_tx(&ll_adv_pdu);
-
- while (!RADIO_DONE)
- ;
-
- tx_end = get_time().le.lo;
-
- if (ll_adv_pdu.header.adv.type ==
- BLE_ADV_HEADER_PDU_TYPE_ADV_NONCONN_IND)
- return EC_SUCCESS;
-
- rv = ble_rx(&ll_rcv_packet, 16000, 1);
-
- if (rv != EC_SUCCESS)
- return rv;
-
- while (!RADIO_DONE)
- ;
-
- tx_rsp_end = get_time().le.lo;
-
- /* Check for valid responses */
- switch (ll_rcv_packet.header.adv.type) {
- case BLE_ADV_HEADER_PDU_TYPE_SCAN_REQ:
- /* Scan requests are only allowed for ADV_IND and SCAN_IND */
- if ((ll_adv_pdu.header.adv.type !=
- BLE_ADV_HEADER_PDU_TYPE_ADV_IND &&
- ll_adv_pdu.header.adv.type !=
- BLE_ADV_HEADER_PDU_TYPE_ADV_SCAN_IND) ||
- /* The advertising address needs to match */
- (memcmp(&ll_rcv_packet.payload[BLUETOOTH_ADDR_OCTETS],
- &ll_adv_pdu.payload[0], BLUETOOTH_ADDR_OCTETS))) {
- /* Don't send the scan response */
- radio_disable();
- return rv;
- }
- break;
- case BLE_ADV_HEADER_PDU_TYPE_CONNECT_REQ:
- /* Don't send a scan response */
- radio_disable();
- /* Connecting is only allowed for ADV_IND and ADV_DIRECT_IND */
- if (ll_adv_pdu.header.adv.type !=
- BLE_ADV_HEADER_PDU_TYPE_ADV_IND &&
- ll_adv_pdu.header.adv.type !=
- BLE_ADV_HEADER_PDU_TYPE_ADV_DIRECT_IND)
- return rv;
- /* The advertising address needs to match */
- if (memcmp(&ll_rcv_packet.payload[BLUETOOTH_ADDR_OCTETS],
- &ll_adv_pdu.payload[0], BLUETOOTH_ADDR_OCTETS))
- return rv;
- /* The InitAddr address needs to match for ADV_DIRECT_IND */
- if (ll_adv_pdu.header.adv.type ==
- BLE_ADV_HEADER_PDU_TYPE_ADV_DIRECT_IND &&
- memcmp(&ll_adv_pdu.payload[BLUETOOTH_ADDR_OCTETS],
- &ll_rcv_packet.payload[0], BLUETOOTH_ADDR_OCTETS))
- return rv;
-
- /* Mark time that connect was received */
- time_of_connect_req = NRF51_TIMER_CC(0, 1);
-
- /*
- * Enter connection state upon receiving
- * a connect request packet
- */
- ll_state = CONNECTION;
-
- return rv;
- break;
- default: /* Unhandled response packet */
- radio_disable();
- return rv;
- break;
- }
-
- CPRINTF("ADV %u Response %u %u\n", tx_end, rsp_end, tx_rsp_end);
-
- return rv;
-}
-
-int ble_ll_adv_event(void)
-{
- int chan_idx;
- int rv = EC_SUCCESS;
-
- for (chan_idx = 0; chan_idx < 3; chan_idx++) {
- if (ll_adv_params.advChannelMap & BIT(chan_idx)) {
- rv = ble_ll_adv(chan_idx + 37);
- if (rv != EC_SUCCESS)
- return rv;
- }
- }
-
- return rv;
-}
-
-
-void print_connection_state(void)
-{
- CPRINTF("vvvvvvvvvvvvvvvvvvvCONNECTION STATEvvvvvvvvvvvvvvvvvvv\n");
- CPRINTF("Number of connections events processed: %d\n", ll_conn_events);
- CPRINTF("Recovered from %d bad receives.\n", errors_recovered);
- CPRINTF("Access addr(hex): %x\n", conn_params.access_addr);
- CPRINTF("win_size(hex): %x\n", conn_params.win_size);
- CPRINTF("win_offset(hex): %x\n", conn_params.win_offset);
- CPRINTF("interval(hex): %x\n", conn_params.interval);
- CPRINTF("latency(hex): %x\n", conn_params.latency);
- CPRINTF("timeout(hex): %x\n", conn_params.timeout);
- CPRINTF("channel_map(hex): %llx\n", conn_params.channel_map);
- CPRINTF("hop(hex): %x\n", conn_params.hop_increment);
- CPRINTF("SCA(hex): %x\n", conn_params.sleep_clock_accuracy);
- CPRINTF("transmitWindowOffset: %d\n", conn_params.transmitWindowOffset);
- CPRINTF("connInterval: %d\n", conn_params.connInterval);
- CPRINTF("transmitWindowSize: %d\n", conn_params.transmitWindowSize);
- CPRINTF("^^^^^^^^^^^^^^^^^^^CONNECTION STATE^^^^^^^^^^^^^^^^^^^\n");
-}
-
-int connected_communicate(void)
-{
- int rv;
- long sleep_time;
- int offset = 0;
- uint64_t listen_time;
- uint8_t comm_channel = get_next_data_channel(&remap_table);
-
- if (num_consecutive_failures > 0) {
- ble_radio_init(conn_params.access_addr,
- conn_params.crc_init_val);
- NRF51_RADIO_FREQUENCY =
- NRF51_RADIO_FREQUENCY_VAL(chan2freq(comm_channel));
- NRF51_RADIO_DATAWHITEIV = comm_channel;
- listen_time = last_receive_time + conn_params.connInterval
- - get_time().val + conn_params.transmitWindowSize;
-
- /*
- * This listens for 1.25 times the expected amount
- * of time. This is a margin of error. This line is
- * only called when a connection has failed (a missed
- * packet). The peripheral and the controller could have
- * missed this packet due to a disagreement on when
- * the packet should have arrived. We listen for
- * slightly longer than expected in the case that
- * there was a timing disagreement.
- */
- rv = ble_rx(&ll_rcv_packet,
- listen_time + (listen_time >> 2), 0);
- } else {
- if (!is_first_data_packet) {
- sleep_time = receive_time +
- conn_params.connInterval - get_time().val;
- /*
- * The time slept is 31/32 (96.875%) of the calculated
- * required sleep time because the code to receive
- * packets requires time to set up.
- */
- usleep(sleep_time - (sleep_time >> 5));
- } else {
- last_receive_time = time_of_connect_req;
- sleep_time = TRANSMIT_WINDOW_OFFSET_CONSTANT +
- conn_params.transmitWindowOffset +
- time_of_connect_req - get_time().val;
- if (sleep_time >= 0) {
- /*
- * Radio is on for longer than needed for first
- * packet to make sure that it is received.
- */
- usleep(sleep_time - (sleep_time >> 2));
- } else {
- return EC_ERROR_TIMEOUT;
- }
- }
-
- ble_radio_init(conn_params.access_addr,
- conn_params.crc_init_val);
- NRF51_RADIO_FREQUENCY =
- NRF51_RADIO_FREQUENCY_VAL(chan2freq(comm_channel));
- NRF51_RADIO_DATAWHITEIV = comm_channel;
-
- /*
- * Timing the transmit window is very hard to do when the code
- * executing has actual effect on the timing. To combat this,
- * the radio starts a little early, and terminates when the
- * window normally should. The variable 'offset' represents
- * how early the window opens in microseconds.
- */
- if (!is_first_data_packet)
- offset = last_receive_time + conn_params.connInterval
- - get_time().val;
- else
- offset = 0;
-
- rv = ble_rx(&ll_rcv_packet,
- offset + conn_params.transmitWindowSize,
- 0);
- }
-
- /*
- * The radio shortcuts have been set up so that transmission
- * occurs automatically after receiving. The radio just needs
- * to know where to find the packet to be sent.
- */
- NRF51_RADIO_PACKETPTR = (uint32_t)packet_tb_sent;
-
- receive_time = NRF51_TIMER_CC(0, 1);
- if (rv != EC_SUCCESS)
- receive_time = last_receive_time + conn_params.connInterval;
-
- while (!RADIO_DONE)
- ;
-
- last_receive_time = receive_time;
- is_first_data_packet = 0;
-
- return rv;
-}
-
-static uint32_t ll_adv_events;
-static timestamp_t deadline;
-static uint32_t start, end;
-
-void bluetooth_ll_task(void)
-{
- uint64_t last_rx_time = 0;
- CPRINTS("LL task init");
-
- while (1) {
- switch (ll_state) {
- case ADVERTISING:
-
- if (deadline.val == 0) {
- CPRINTS("ADV @%pP", &ll_adv_pdu);
- deadline.val = get_time().val +
- (uint32_t)ll_adv_timeout_us;
- ll_adv_events = 0;
- }
-
- ble_ll_adv_event();
- ll_adv_events++;
-
- if (ll_state == CONNECTION) {
- receive_time = 0;
- break;
- }
- /* sleep for 0-10ms */
- usleep(ll_adv_interval_us + ll_pseudo_rand(10000));
-
- if (get_time().val > deadline.val) {
- ll_state = STANDBY;
- break;
- }
- break;
- case STANDBY:
- deadline.val = 0;
- CPRINTS("Standby %d events", ll_adv_events);
- ll_adv_events = 0;
- ll_conn_events = 0;
- task_wait_event(-1);
- connection_initialized = 0;
- errors_recovered = 0;
- break;
- case TEST_RX:
- if (ble_test_rx() == HCI_SUCCESS)
- ll_test_packets++;
- /* Packets come every 625us, sleep to save power */
- usleep(300);
- break;
- case TEST_TX:
- start = get_time().le.lo;
- ble_test_tx();
- ll_test_packets++;
- end = get_time().le.lo;
- usleep(625 - 82 - (end-start)); /* 625us */
- break;
- case UNINITIALIZED:
- ble_radio_init(BLE_ADV_ACCESS_ADDRESS, BLE_ADV_CRCINIT);
- ll_adv_events = 0;
- task_wait_event(-1);
- connection_initialized = 0;
- packet_tb_sent = &tx_packet_1;
- set_empty_data_packet(&tx_packet_1);
- break;
- case CONNECTION:
- if (!connection_initialized) {
- if (initialize_connection() != HCI_SUCCESS) {
- ll_state = STANDBY;
- break;
- }
- connection_initialized = 1;
- last_rx_time = NRF51_TIMER_CC(0, 1);
- }
-
- if (connected_communicate() == EC_SUCCESS) {
- if (num_consecutive_failures > 0)
- ++errors_recovered;
- num_consecutive_failures = 0;
- last_rx_time = get_time().val;
- } else {
- num_consecutive_failures++;
- if ((get_time().val - last_rx_time) >
- conn_params.connSupervisionTimeout) {
-
- ll_state = STANDBY;
- CPRINTF("EXITING CONNECTION STATE "
- "DUE TO TIMEOUT.\n");
- }
- }
- ++ll_conn_events;
-
- if (ll_state == STANDBY) {
- CPRINTF("Exiting connection state/Entering "
- "Standby state after %d connections "
- "events\n", ll_conn_events);
- print_connection_state();
- }
- break;
- default:
- CPRINTS("Unhandled State ll_state = %d", ll_state);
- ll_state = UNINITIALIZED;
- task_wait_event(-1);
- }
- }
-}
-
diff --git a/common/build.mk b/common/build.mk
index a1a956f9ab..cfc023be5a 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -306,9 +306,3 @@ $(out)/rma_key_from_blob.h: board/$(BOARD)/$(BLOB_FILE) util/bin2h.sh
$(Q)util/bin2h.sh RMA_KEY_BLOB $< $@
endif
-
-include $(_common_dir)fpsensor/build.mk
-include $(_common_dir)usbc/build.mk
-
-include $(_common_dir)mock/build.mk
-common-y+=$(foreach m,$(mock-y),mock/$(m))
diff --git a/common/button.c b/common/button.c
deleted file mode 100644
index 03bdb1234f..0000000000
--- a/common/button.c
+++ /dev/null
@@ -1,892 +0,0 @@
-/* Copyright 2014 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.
- */
-
-/* Button module for Chrome EC */
-
-#include "atomic.h"
-#include "button.h"
-#include "chipset.h"
-#include "common.h"
-#include "compile_time_macros.h"
-#include "console.h"
-#include "gpio.h"
-#include "host_command.h"
-#include "hooks.h"
-#include "keyboard_protocol.h"
-#include "led_common.h"
-#include "mkbp_input_devices.h"
-#include "power_button.h"
-#include "system.h"
-#include "timer.h"
-#include "util.h"
-#include "watchdog.h"
-
-/* Console output macro */
-#define CPRINTS(format, args...) cprints(CC_SWITCH, format, ## args)
-
-struct button_state_t {
- uint64_t debounce_time;
- int debounced_pressed;
-};
-
-static struct button_state_t __bss_slow state[BUTTON_COUNT];
-
-static uint64_t __bss_slow next_deferred_time;
-
-#if defined(CONFIG_CMD_BUTTON) || defined(CONFIG_HOSTCMD_BUTTON)
-#define CONFIG_SIMULATED_BUTTON
-#endif
-
-#ifdef CONFIG_SIMULATED_BUTTON
-/* Bitmask to keep track of simulated state of each button.
- * Bit numbers are aligned to enum button.
- */
-static int sim_button_state;
-
-/*
- * Flip state of associated button type in sim_button_state bitmask.
- * In bitmask, if bit is 1, button is pressed. If bit is 0, button is
- * released.
- *
- * Returns the appropriate GPIO value based on table below:
- * +----------+--------+--------+
- * | state | active | return |
- * +----------+--------+--------+
- * | pressed | high | 1 |
- * | pressed | low | 0 |
- * | released | high | 0 |
- * | released | low | 1 |
- * +----------+--------+--------+
- */
-static int simulated_button_pressed(const struct button_config *button)
-{
- return !!(sim_button_state & BIT(button->type));
-}
-#endif
-
-/*
- * Whether a button is currently pressed.
- */
-static int raw_button_pressed(const struct button_config *button)
-{
- int physical_value = 0;
- int simulated_value = 0;
- if (!(button->flags & BUTTON_FLAG_DISABLED)) {
- if (IS_ENABLED(CONFIG_ADC_BUTTONS) &&
- button_is_adc_detected(button->gpio)) {
- physical_value =
- adc_to_physical_value(button->gpio);
- } else {
- physical_value = (!!gpio_get_level(button->gpio) ==
- !!(button->flags & BUTTON_FLAG_ACTIVE_HIGH));
- }
-#ifdef CONFIG_SIMULATED_BUTTON
- simulated_value = simulated_button_pressed(button);
-#endif
- }
-
- return (simulated_value || physical_value);
-}
-
-#ifdef CONFIG_BUTTON_TRIGGERED_RECOVERY
-
-#ifdef CONFIG_LED_COMMON
-static void button_blink_hw_reinit_led(void)
-{
- int led_state = LED_STATE_ON;
- timestamp_t deadline;
- timestamp_t now = get_time();
-
- /* Blink LED for 3 seconds. */
- deadline.val = now.val + (3 * SECOND);
-
- while (!timestamp_expired(deadline, &now)) {
- led_control(EC_LED_ID_RECOVERY_HW_REINIT_LED, led_state);
- led_state = !led_state;
- watchdog_reload();
- msleep(100);
- now = get_time();
- }
-
- /* Reset LED to default state. */
- led_control(EC_LED_ID_RECOVERY_HW_REINIT_LED, LED_STATE_RESET);
-}
-#endif
-
-/*
- * Whether recovery button (or combination of equivalent buttons) is pressed
- * If a dedicated recovery button is used, any of the buttons can be pressed,
- * otherwise, all the buttons must be pressed.
- */
-static int is_recovery_button_pressed(void)
-{
- int i, pressed;
- for (i = 0; i < recovery_buttons_count; i++) {
- pressed = raw_button_pressed(recovery_buttons[i]);
- if (IS_ENABLED(CONFIG_DEDICATED_RECOVERY_BUTTON)) {
- if (pressed)
- return 1;
- } else {
- if (!pressed)
- return 0;
- }
- }
- return IS_ENABLED(CONFIG_DEDICATED_RECOVERY_BUTTON) ? 0 : 1;
-}
-
-/*
- * If the EC is reset and recovery is requested, then check if HW_REINIT is
- * requested as well. Since the EC reset occurs after volup+voldn+power buttons
- * are held down for 10 seconds, check the state of these buttons for 20 more
- * seconds. If they are still held down all this time, then set host event to
- * indicate HW_REINIT is requested. Also, make sure watchdog is reloaded in
- * order to prevent watchdog from resetting the EC.
- */
-static void button_check_hw_reinit_required(void)
-{
- timestamp_t deadline;
- timestamp_t now = get_time();
-#ifdef CONFIG_LED_COMMON
- uint8_t led_on = 0;
-#endif
-
- deadline.val = now.val + (20 * SECOND);
-
- CPRINTS("Checking for HW_REINIT request");
-
- while (!timestamp_expired(deadline, &now)) {
- if (!is_recovery_button_pressed() ||
- !power_button_signal_asserted()) {
- CPRINTS("No HW_REINIT request");
-#ifdef CONFIG_LED_COMMON
- if (led_on)
- led_control(EC_LED_ID_RECOVERY_HW_REINIT_LED,
- LED_STATE_RESET);
-#endif
- return;
- }
-
-#ifdef CONFIG_LED_COMMON
- if (!led_on) {
- led_control(EC_LED_ID_RECOVERY_HW_REINIT_LED,
- LED_STATE_ON);
- led_on = 1;
- }
-#endif
-
- now = get_time();
- watchdog_reload();
- }
-
- CPRINTS("HW_REINIT requested");
- host_set_single_event(EC_HOST_EVENT_KEYBOARD_RECOVERY_HW_REINIT);
-
-#ifdef CONFIG_LED_COMMON
- button_blink_hw_reinit_led();
-#endif
-}
-
-static int is_recovery_boot(void)
-{
- if (system_jumped_to_this_image())
- return 0;
- if (!(system_get_reset_flags() &
- (EC_RESET_FLAG_RESET_PIN | EC_RESET_FLAG_POWER_ON)))
- return 0;
- if (!is_recovery_button_pressed())
- return 0;
- return 1;
-}
-#endif /* CONFIG_BUTTON_TRIGGERED_RECOVERY */
-
-static void button_reset(enum button button_type,
- const struct button_config *button)
-{
- state[button_type].debounced_pressed = raw_button_pressed(button);
- state[button_type].debounce_time = 0;
- gpio_enable_interrupt(button->gpio);
-}
-
-/*
- * Button initialization.
- */
-void button_init(void)
-{
- int i;
-
- CPRINTS("init buttons");
- next_deferred_time = 0;
- for (i = 0; i < BUTTON_COUNT; i++)
- button_reset(i, &buttons[i]);
-
-#ifdef CONFIG_BUTTON_TRIGGERED_RECOVERY
- if (is_recovery_boot()) {
- system_clear_reset_flags(EC_RESET_FLAG_AP_OFF);
- host_set_single_event(EC_HOST_EVENT_KEYBOARD_RECOVERY);
- button_check_hw_reinit_required();
- }
-#endif /* defined(CONFIG_BUTTON_TRIGGERED_RECOVERY) */
-}
-
-#ifdef CONFIG_BUTTONS_RUNTIME_CONFIG
-int button_reassign_gpio(enum button button_type, enum gpio_signal gpio)
-{
- if (button_type >= BUTTON_COUNT)
- return EC_ERROR_INVAL;
-
- /* Disable currently assigned interrupt */
- gpio_disable_interrupt(buttons[button_type].gpio);
-
- /* Reconfigure GPIO and enable the new interrupt */
- buttons[button_type].gpio = gpio;
- button_reset(button_type, &buttons[button_type]);
-
- return EC_SUCCESS;
-}
-
-int button_disable_gpio(enum button button_type)
-{
- if (button_type >= BUTTON_COUNT)
- return EC_ERROR_INVAL;
-
- /* Disable GPIO interrupt */
- gpio_disable_interrupt(buttons[button_type].gpio);
- /* Mark button as disabled */
- buttons[button_type].flags |= BUTTON_FLAG_DISABLED;
-
- return EC_SUCCESS;
-}
-#endif
-
-
-/*
- * Handle debounced button changing state.
- */
-
-static void button_change_deferred(void);
-DECLARE_DEFERRED(button_change_deferred);
-
-#ifdef CONFIG_EMULATED_SYSRQ
-static void debug_mode_handle(void);
-DECLARE_DEFERRED(debug_mode_handle);
-DECLARE_HOOK(HOOK_POWER_BUTTON_CHANGE, debug_mode_handle, HOOK_PRIO_LAST);
-#endif
-
-static void button_change_deferred(void)
-{
- int i;
- int new_pressed;
- uint64_t soonest_debounce_time = 0;
- uint64_t time_now = get_time().val;
-
- for (i = 0; i < BUTTON_COUNT; i++) {
- /* Skip this button if we are not waiting to debounce */
- if (state[i].debounce_time == 0)
- continue;
-
- if (state[i].debounce_time <= time_now) {
- /* Check if the state has changed */
- new_pressed = raw_button_pressed(&buttons[i]);
- if (state[i].debounced_pressed != new_pressed) {
- state[i].debounced_pressed = new_pressed;
-#ifdef CONFIG_EMULATED_SYSRQ
- /*
- * Calling deferred function for handling debug
- * mode so that button change processing is not
- * delayed.
- */
-#ifdef CONFIG_DEDICATED_RECOVERY_BUTTON
- /*
- * Only the direct signal is used for sysrq.
- * H1_EC_RECOVERY_BTN_ODL doesn't reflect the
- * true state of the recovery button.
- */
- if (i == BUTTON_RECOVERY)
-#endif
- hook_call_deferred(
- &debug_mode_handle_data, 0);
-#endif
- CPRINTS("Button '%s' was %s",
- buttons[i].name, new_pressed ?
- "pressed" : "released");
- if (IS_ENABLED(CONFIG_MKBP_INPUT_DEVICES)) {
- mkbp_button_update(buttons[i].type,
- new_pressed);
- } else if (IS_ENABLED(HAS_TASK_KEYPROTO)) {
- keyboard_update_button(buttons[i].type,
- new_pressed);
- }
- }
-
- /* Clear the debounce time to stop checking it */
- state[i].debounce_time = 0;
- } else {
- /*
- * Make sure the next deferred call happens on or before
- * each button needs it.
- */
- soonest_debounce_time = (soonest_debounce_time == 0) ?
- state[i].debounce_time :
- MIN(soonest_debounce_time,
- state[i].debounce_time);
- }
- }
-
- if (soonest_debounce_time != 0) {
- next_deferred_time = soonest_debounce_time;
- hook_call_deferred(&button_change_deferred_data,
- next_deferred_time - time_now);
- }
-}
-
-/*
- * Handle a button interrupt.
- */
-void button_interrupt(enum gpio_signal signal)
-{
- int i;
- uint64_t time_now = get_time().val;
-
- for (i = 0; i < BUTTON_COUNT; i++) {
- if (buttons[i].gpio != signal ||
- (buttons[i].flags & BUTTON_FLAG_DISABLED))
- continue;
-
- state[i].debounce_time = time_now + buttons[i].debounce_us;
- if (next_deferred_time <= time_now ||
- next_deferred_time > state[i].debounce_time) {
- next_deferred_time = state[i].debounce_time;
- hook_call_deferred(&button_change_deferred_data,
- next_deferred_time - time_now);
- }
- break;
- }
-}
-
-#ifdef CONFIG_SIMULATED_BUTTON
-static int button_present(enum keyboard_button_type type)
-{
- int i;
-
- for (i = 0; i < BUTTON_COUNT; i++)
- if (buttons[i].type == type)
- break;
-
- return i;
-}
-
-static void button_interrupt_simulate(int button)
-{
- button_interrupt(buttons[button].gpio);
-}
-
-static void simulate_button_release_deferred(void)
-{
- int button_idx;
-
- /* 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)) {
- /* Set state of the button as released */
- atomic_clear_bits(&sim_button_state,
- BIT(buttons[button_idx].type));
-
- button_interrupt_simulate(button_idx);
- }
- }
-}
-DECLARE_DEFERRED(simulate_button_release_deferred);
-
-static void simulate_button(uint32_t button_mask, int press_ms)
-{
- int button_idx;
-
- /* Press the button */
- for (button_idx = 0; button_idx < BUTTON_COUNT; button_idx++) {
- if (button_mask & BIT(button_idx)) {
- /* Set state of the button as pressed */
- atomic_or(&sim_button_state,
- BIT(buttons[button_idx].type));
-
- button_interrupt_simulate(button_idx);
- }
- }
-
- /* Defer the button release for specified duration */
- hook_call_deferred(&simulate_button_release_deferred_data,
- press_ms * MSEC);
-}
-#endif /* #ifdef CONFIG_SIMULATED_BUTTON */
-
-#ifdef CONFIG_CMD_BUTTON
-static int console_command_button(int argc, char **argv)
-{
- int press_ms = 50;
- char *e;
- int argv_idx;
- int button = BUTTON_COUNT;
- uint32_t button_mask = 0;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- for (argv_idx = 1; argv_idx < argc; argv_idx++) {
- if (!strcasecmp(argv[argv_idx], "vup"))
- button = button_present(KEYBOARD_BUTTON_VOLUME_UP);
- else if (!strcasecmp(argv[argv_idx], "vdown"))
- button = button_present(KEYBOARD_BUTTON_VOLUME_DOWN);
- else if (!strcasecmp(argv[argv_idx], "rec"))
- button = button_present(KEYBOARD_BUTTON_RECOVERY);
- else {
- /* If last parameter check if it is an integer. */
- if (argv_idx == argc - 1) {
- press_ms = strtoi(argv[argv_idx], &e, 0);
- /* If integer, break out of the loop. */
- if (!*e)
- break;
- }
- button = BUTTON_COUNT;
- }
-
- if (button == BUTTON_COUNT)
- return EC_ERROR_PARAM1 + argv_idx - 1;
-
- button_mask |= BIT(button);
- }
-
- if (!button_mask)
- return EC_SUCCESS;
-
- simulate_button(button_mask, press_ms);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(button, console_command_button,
- "vup|vdown|rec msec",
- "Simulate button press");
-#endif /* CONFIG_CMD_BUTTON */
-
-#ifdef CONFIG_HOSTCMD_BUTTON
-static enum ec_status host_command_button(struct host_cmd_handler_args *args)
-{
- const struct ec_params_button *p = args->params;
- int idx;
- uint32_t button_mask = 0;
-
- /* Only available on unlocked systems */
- if (system_is_locked())
- return EC_RES_ACCESS_DENIED;
-
- for (idx = 0; idx < KEYBOARD_BUTTON_COUNT; idx++) {
- if (p->btn_mask & BIT(idx))
- button_mask |= BIT(button_present(idx));
- }
-
- simulate_button(button_mask, p->press_ms);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_BUTTON, host_command_button, EC_VER_MASK(0));
-
-#endif /* CONFIG_HOSTCMD_BUTTON */
-
-
-#ifdef CONFIG_EMULATED_SYSRQ
-
-#ifdef CONFIG_DEDICATED_RECOVERY_BUTTON
-
-/*
- * Simplified sysrq handler
- *
- * In simplified sysrq, user can
- * - press and release recovery button to send one sysrq event to the host
- * - press and hold recovery button for 4 seconds to reset the AP (warm reset)
- */
-static void debug_mode_handle(void)
-{
- static int recovery_button_pressed = 0;
-
- if (!recovery_button_pressed) {
- if (is_recovery_button_pressed()) {
- /* User pressed recovery button. Wait for 4 seconds
- * to see if warm reset is requested. */
- recovery_button_pressed = 1;
- hook_call_deferred(&debug_mode_handle_data, 4 * SECOND);
- }
- } else {
- /* We come here when recovery button is released or when
- * 4 sec elapsed with recovery button still pressed. */
- if (!is_recovery_button_pressed()) {
- /* Cancel pending timer */
- hook_call_deferred(&debug_mode_handle_data, -1);
- host_send_sysrq('x');
- CPRINTS("DEBUG MODE: sysrq-x sent");
- } else {
- chipset_reset(CHIPSET_RESET_DBG_WARM_REBOOT);
- CPRINTS("DEBUG MODE: Warm reset triggered");
- }
- recovery_button_pressed = 0;
- }
-}
-
-#else /* CONFIG_DEDICATED_RECOVERY_BUTTON */
-
-enum debug_state {
- STATE_DEBUG_NONE,
- STATE_DEBUG_CHECK,
- STATE_STAGING,
- STATE_DEBUG_MODE_ACTIVE,
- STATE_SYSRQ_PATH,
- STATE_WARM_RESET_PATH,
- STATE_SYSRQ_EXEC,
- STATE_WARM_RESET_EXEC,
-};
-
-#define DEBUG_BTN_POWER BIT(0)
-#define DEBUG_BTN_VOL_UP BIT(1)
-#define DEBUG_BTN_VOL_DN BIT(2)
-#define DEBUG_TIMEOUT (10 * SECOND)
-
-static enum debug_state curr_debug_state = STATE_DEBUG_NONE;
-static enum debug_state next_debug_state = STATE_DEBUG_NONE;
-static timestamp_t debug_state_deadline;
-static int debug_button_hit_count;
-
-static int debug_button_mask(void)
-{
- int mask = 0;
-
- /* Get power button state */
- if (power_button_is_pressed())
- mask |= DEBUG_BTN_POWER;
-
- /* Get volume up state */
- if (state[BUTTON_VOLUME_UP].debounced_pressed)
- mask |= DEBUG_BTN_VOL_UP;
-
- /* Get volume down state */
- if (state[BUTTON_VOLUME_DOWN].debounced_pressed)
- mask |= DEBUG_BTN_VOL_DN;
-
- return mask;
-}
-
-static int debug_button_pressed(int mask)
-{
- return debug_button_mask() == mask;
-}
-
-#ifdef CONFIG_LED_COMMON
-static int debug_mode_blink_led(void)
-{
- return ((curr_debug_state != STATE_DEBUG_NONE) &&
- (curr_debug_state != STATE_DEBUG_CHECK));
-}
-#endif
-
-static void debug_mode_transition(enum debug_state next_state)
-{
- timestamp_t now = get_time();
-#ifdef CONFIG_LED_COMMON
- int curr_blink_state = debug_mode_blink_led();
-#endif
-
- /* Cancel any deferred calls. */
- hook_call_deferred(&debug_mode_handle_data, -1);
-
- /* Update current debug mode state. */
- curr_debug_state = next_state;
-
- /* Set deadline to 10seconds from current time. */
- debug_state_deadline.val = now.val + DEBUG_TIMEOUT;
-
- switch (curr_debug_state) {
- case STATE_DEBUG_NONE:
- /*
- * Nothing is done here since some states can transition to
- * STATE_DEBUG_NONE in this function. Wait until all other
- * states are evaluated to take the action for STATE_NONE.
- */
- break;
- case STATE_DEBUG_CHECK:
- case STATE_STAGING:
- break;
- case STATE_DEBUG_MODE_ACTIVE:
- debug_button_hit_count = 0;
- break;
- case STATE_SYSRQ_PATH:
- /*
- * Increment debug_button_hit_count and ensure it does not go
- * past 3. If it exceeds the limit transition to STATE_NONE.
- */
- debug_button_hit_count++;
- if (debug_button_hit_count == 4)
- curr_debug_state = STATE_DEBUG_NONE;
- break;
- case STATE_WARM_RESET_PATH:
- break;
- case STATE_SYSRQ_EXEC:
- /*
- * Depending upon debug_button_hit_count, send appropriate
- * number of sysrq events to host and transition to STATE_NONE.
- */
- while (debug_button_hit_count) {
- host_send_sysrq('x');
- CPRINTS("DEBUG MODE: sysrq-x sent");
- debug_button_hit_count--;
- }
- curr_debug_state = STATE_DEBUG_NONE;
- break;
- case STATE_WARM_RESET_EXEC:
- /* Warm reset the host and transition to STATE_NONE. */
- chipset_reset(CHIPSET_RESET_DBG_WARM_REBOOT);
- CPRINTS("DEBUG MODE: Warm reset triggered");
- curr_debug_state = STATE_DEBUG_NONE;
- break;
- default:
- curr_debug_state = STATE_DEBUG_NONE;
- }
-
- if (curr_debug_state != STATE_DEBUG_NONE) {
- /*
- * Schedule a deferred call after DEBUG_TIMEOUT to check for
- * button state if it does not change during the timeout
- * duration.
- */
- hook_call_deferred(&debug_mode_handle_data, DEBUG_TIMEOUT);
- return;
- }
-
- /* If state machine reached initial state, reset all variables. */
- CPRINTS("DEBUG MODE: Exit!");
- next_debug_state = STATE_DEBUG_NONE;
- debug_state_deadline.val = 0;
- debug_button_hit_count = 0;
-#ifdef CONFIG_LED_COMMON
- if (curr_blink_state)
- led_control(EC_LED_ID_SYSRQ_DEBUG_LED, LED_STATE_RESET);
-#endif
-}
-
-static void debug_mode_handle(void)
-{
- int mask;
-
- switch (curr_debug_state) {
- case STATE_DEBUG_NONE:
- /*
- * If user pressed Vup+Vdn, check for next 10 seconds to see if
- * user keeps holding the keys.
- */
- if (debug_button_pressed(DEBUG_BTN_VOL_UP | DEBUG_BTN_VOL_DN))
- debug_mode_transition(STATE_DEBUG_CHECK);
- break;
- case STATE_DEBUG_CHECK:
- /*
- * If no key is pressed or any key combo other than Vup+Vdn is
- * held, then quit debug check mode.
- */
- if (!debug_button_pressed(DEBUG_BTN_VOL_UP | DEBUG_BTN_VOL_DN))
- debug_mode_transition(STATE_DEBUG_NONE);
- else if (timestamp_expired(debug_state_deadline, NULL)) {
- /*
- * If Vup+Vdn are held down for 10 seconds, then its
- * time to enter debug mode.
- */
- CPRINTS("DEBUG MODE: Active!");
- next_debug_state = STATE_DEBUG_MODE_ACTIVE;
- debug_mode_transition(STATE_STAGING);
- }
- break;
- case STATE_STAGING:
- mask = debug_button_mask();
-
- /* If no button is pressed, transition to next state. */
- if (!mask) {
- debug_mode_transition(next_debug_state);
- return;
- }
-
- /* Exit debug mode if keys are stuck for > 10 seconds. */
- if (timestamp_expired(debug_state_deadline, NULL))
- debug_mode_transition(STATE_DEBUG_NONE);
- else {
- timestamp_t now = get_time();
-
- /*
- * Schedule a deferred call in case timeout hasn't
- * occurred yet.
- */
- hook_call_deferred(&debug_mode_handle_data,
- (debug_state_deadline.val - now.val));
- }
-
- break;
- case STATE_DEBUG_MODE_ACTIVE:
- mask = debug_button_mask();
-
- /*
- * Continue in this state if button is not pressed and timeout
- * has not occurred.
- */
- if (!mask && !timestamp_expired(debug_state_deadline, NULL))
- return;
-
- /* Exit debug mode if valid buttons are not pressed. */
- if ((mask != DEBUG_BTN_VOL_UP) && (mask != DEBUG_BTN_VOL_DN)) {
- debug_mode_transition(STATE_DEBUG_NONE);
- return;
- }
-
- /*
- * Transition to STAGING state with next state set to:
- * 1. SYSRQ_PATH : If Vup was pressed.
- * 2. WARM_RESET_PATH: If Vdn was pressed.
- */
- if (mask == DEBUG_BTN_VOL_UP)
- next_debug_state = STATE_SYSRQ_PATH;
- else
- next_debug_state = STATE_WARM_RESET_PATH;
-
- debug_mode_transition(STATE_STAGING);
- break;
- case STATE_SYSRQ_PATH:
- mask = debug_button_mask();
-
- /*
- * Continue in this state if button is not pressed and timeout
- * has not occurred.
- */
- if (!mask && !timestamp_expired(debug_state_deadline, NULL))
- return;
-
- /* Exit debug mode if valid buttons are not pressed. */
- if ((mask != DEBUG_BTN_VOL_UP) && (mask != DEBUG_BTN_VOL_DN)) {
- debug_mode_transition(STATE_DEBUG_NONE);
- return;
- }
-
- if (mask == DEBUG_BTN_VOL_UP) {
- /*
- * Else transition to STAGING state with next state set
- * to SYSRQ_PATH.
- */
- next_debug_state = STATE_SYSRQ_PATH;
- } else {
- /*
- * Else if Vdn is pressed, transition to STAGING with
- * next state set to SYSRQ_EXEC.
- */
- next_debug_state = STATE_SYSRQ_EXEC;
- }
- debug_mode_transition(STATE_STAGING);
- break;
- case STATE_WARM_RESET_PATH:
- mask = debug_button_mask();
-
- /*
- * Continue in this state if button is not pressed and timeout
- * has not occurred.
- */
- if (!mask && !timestamp_expired(debug_state_deadline, NULL))
- return;
-
- /* Exit debug mode if valid buttons are not pressed. */
- if (mask != DEBUG_BTN_VOL_UP) {
- debug_mode_transition(STATE_DEBUG_NONE);
- return;
- }
-
- next_debug_state = STATE_WARM_RESET_EXEC;
- debug_mode_transition(STATE_STAGING);
- break;
- case STATE_SYSRQ_EXEC:
- case STATE_WARM_RESET_EXEC:
- default:
- debug_mode_transition(STATE_DEBUG_NONE);
- break;
- }
-}
-
-#ifdef CONFIG_LED_COMMON
-static void debug_led_tick(void)
-{
- static int led_state = LED_STATE_OFF;
-
- if (debug_mode_blink_led()) {
- led_state = !led_state;
- led_control(EC_LED_ID_SYSRQ_DEBUG_LED, led_state);
- }
-}
-DECLARE_HOOK(HOOK_TICK, debug_led_tick, HOOK_PRIO_DEFAULT);
-#endif /* CONFIG_LED_COMMON */
-
-#endif /* !CONFIG_DEDICATED_RECOVERY_BUTTON */
-#endif /* CONFIG_EMULATED_SYSRQ */
-
-#ifndef CONFIG_BUTTONS_RUNTIME_CONFIG
-const struct button_config buttons[BUTTON_COUNT] = {
-#else
-struct button_config buttons[BUTTON_COUNT] = {
-#endif
-#ifdef CONFIG_VOLUME_BUTTONS
- [BUTTON_VOLUME_UP] = {
- .name = "Volume Up",
- .type = KEYBOARD_BUTTON_VOLUME_UP,
- .gpio = GPIO_VOLUME_UP_L,
- .debounce_us = BUTTON_DEBOUNCE_US,
- .flags = 0,
- },
-
- [BUTTON_VOLUME_DOWN] = {
- .name = "Volume Down",
- .type = KEYBOARD_BUTTON_VOLUME_DOWN,
- .gpio = GPIO_VOLUME_DOWN_L,
- .debounce_us = BUTTON_DEBOUNCE_US,
- .flags = 0,
- },
-
-#endif
-#if defined(CONFIG_DEDICATED_RECOVERY_BUTTON)
- [BUTTON_RECOVERY] = {
- .name = "Recovery",
- .type = KEYBOARD_BUTTON_RECOVERY,
- .gpio = GPIO_RECOVERY_L,
- .debounce_us = BUTTON_DEBOUNCE_US,
- .flags = 0,
- },
-#ifdef CONFIG_DEDICATED_RECOVERY_BUTTON_2
- [BUTTON_RECOVERY_2] = {
- .name = "Recovery2",
- .type = KEYBOARD_BUTTON_RECOVERY,
- .gpio = GPIO_RECOVERY_L_2,
- .debounce_us = BUTTON_DEBOUNCE_US,
- .flags = 0,
- }
-#endif /* defined(CONFIG_DEDICATED_RECOVERY_BUTTON_2) */
-#endif /* defined(CONFIG_DEDICATED_RECOVERY_BUTTON) */
-};
-
-#ifdef CONFIG_BUTTON_TRIGGERED_RECOVERY
-/*
- * Prefer the dedicated recovery button over the volume buttons if
- * both are present.
- */
-const struct button_config *recovery_buttons[] = {
-#ifdef CONFIG_DEDICATED_RECOVERY_BUTTON
- &buttons[BUTTON_RECOVERY],
-
-#ifdef CONFIG_DEDICATED_RECOVERY_BUTTON_2
- &buttons[BUTTON_RECOVERY_2],
-#endif /* defined(CONFIG_BUTTON_TRIGGERED_RECOVERY_2) */
-
-#elif defined(CONFIG_VOLUME_BUTTONS)
- &buttons[BUTTON_VOLUME_DOWN],
- &buttons[BUTTON_VOLUME_UP],
-#endif /* defined(CONFIG_VOLUME_BUTTONS) */
-};
-const int recovery_buttons_count = ARRAY_SIZE(recovery_buttons);
-#endif /* defined(CONFIG_BUTTON_TRIGGERED_RECOVERY) */
diff --git a/common/capsense.c b/common/capsense.c
deleted file mode 100644
index b2413ac61f..0000000000
--- a/common/capsense.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* Copyright 2014 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.
- */
-
-#include "common.h"
-#include "console.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "i2c.h"
-#include "keyboard_protocol.h"
-#include "timer.h"
-
-/* Console output macro */
-#define CPRINTF(format, args...) cprintf(CC_KEYBOARD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args)
-
-#define CAPSENSE_I2C_ADDR 0x08
-#define CAPSENSE_MASK_BITS 8
-#define CAPSENSE_POLL_INTERVAL (20 * MSEC)
-
-static int capsense_read_bitmask(void)
-{
- int rv;
- uint8_t val = 0;
-
- rv = i2c_xfer(I2C_PORT_CAPSENSE, CAPSENSE_I2C_ADDR,
- 0, 0, &val, 1);
-
- if (rv)
- CPRINTS("%s failed: error %d", __func__, rv);
-
- return val;
-}
-
-static void capsense_init(void)
-{
- gpio_enable_interrupt(GPIO_CAPSENSE_INT_L);
-}
-DECLARE_HOOK(HOOK_INIT, capsense_init, HOOK_PRIO_DEFAULT);
-
-/*
- * Keep checking polling the capsense until all the buttons are released.
- * We're not worrying about debouncing, since the capsense module should do
- * that for us.
- */
-static void capsense_change_deferred(void)
-{
- static uint8_t cur_val;
- uint8_t new_val;
- int i, n, c;
-
- new_val = capsense_read_bitmask();
- if (new_val != cur_val) {
- CPRINTF("[%pT capsense 0x%02x: ",
- PRINTF_TIMESTAMP_NOW, new_val);
- for (i = 0; i < CAPSENSE_MASK_BITS; i++) {
- /* See what changed */
- n = (new_val >> i) & 0x01;
- c = (cur_val >> i) & 0x01;
- CPRINTF("%s", n ? " X " : " _ ");
- if (n == c)
- continue;
-#ifdef HAS_TASK_KEYPROTO
- /* Treat it as a keyboard event. */
- keyboard_update_button(i + KEYBOARD_BUTTON_CAPSENSE_1,
- n);
-#endif
- }
- CPRINTF("]\n");
- cur_val = new_val;
- }
-
- if (cur_val)
- hook_call_deferred(&capsense_change_deferred_data,
- CAPSENSE_POLL_INTERVAL);
-}
-DECLARE_DEFERRED(capsense_change_deferred);
-
-/*
- * Somebody's poking at us.
- */
-void capsense_interrupt(enum gpio_signal signal)
-{
- hook_call_deferred(&capsense_change_deferred_data, 0);
-}
diff --git a/common/cbi.c b/common/cbi.c
deleted file mode 100644
index 345e313c54..0000000000
--- a/common/cbi.c
+++ /dev/null
@@ -1,578 +0,0 @@
-/* Copyright 2018 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.
- *
- * Cros Board Info
- */
-
-#include "common.h"
-#include "console.h"
-#include "crc8.h"
-#include "cros_board_info.h"
-#include "gpio.h"
-#include "host_command.h"
-#include "i2c.h"
-#include "timer.h"
-
-#ifdef HOST_TOOLS_BUILD
-#include <string.h>
-#else
-#include "util.h"
-#endif
-
-/*
- * Functions and variables defined here shared with host tools (e.g. cbi-util).
- * TODO: Move these to common/cbi/cbi.c and common/cbi/utils.c if they grow.
- */
-uint8_t cbi_crc8(const struct cbi_header *h)
-{
- return cros_crc8((uint8_t *)&h->crc + 1,
- h->total_size - sizeof(h->magic) - sizeof(h->crc));
-}
-
-uint8_t *cbi_set_data(uint8_t *p, enum cbi_data_tag tag,
- const void *buf, int size)
-{
- struct cbi_data *d = (struct cbi_data *)p;
-
- /*
- * If size of the data to be added is zero, then no need to add the tag
- * as well.
- */
- if (size == 0)
- return p;
-
- d->tag = tag;
- d->size = size;
- memcpy(d->value, buf, size);
- p += sizeof(*d) + size;
- return p;
-}
-
-uint8_t *cbi_set_string(uint8_t *p, enum cbi_data_tag tag, const char *str)
-{
- if (str == NULL)
- return p;
-
- return cbi_set_data(p, tag, str, strlen(str) + 1);
-}
-
-struct cbi_data *cbi_find_tag(const void *buf, enum cbi_data_tag tag)
-{
- struct cbi_data *d;
- const struct cbi_header *h = buf;
- const uint8_t *p;
- for (p = h->data; p + sizeof(*d) < (uint8_t *)buf + h->total_size;) {
- d = (struct cbi_data *)p;
- if (d->tag == tag)
- return d;
- p += sizeof(*d) + d->size;
- }
- return NULL;
-}
-
-/*
- * Functions and variables specific to EC firmware
- */
-#ifndef HOST_TOOLS_BUILD
-
-#define CPRINTS(format, args...) cprints(CC_SYSTEM, "CBI " format, ## args)
-
-static int cache_status = CBI_CACHE_STATUS_INVALID;
-static uint8_t cbi[CBI_IMAGE_SIZE];
-static struct cbi_header * const head = (struct cbi_header *)cbi;
-
-int cbi_create(void)
-{
- memset(cbi, 0, sizeof(cbi));
- memcpy(head->magic, cbi_magic, sizeof(cbi_magic));
- head->total_size = sizeof(*head);
- head->major_version = CBI_VERSION_MAJOR;
- head->minor_version = CBI_VERSION_MINOR;
- head->crc = cbi_crc8(head);
- cache_status = CBI_CACHE_STATUS_SYNCED;
-
- return EC_SUCCESS;
-}
-
-void cbi_invalidate_cache(void)
-{
- cache_status = CBI_CACHE_STATUS_INVALID;
-}
-
-int cbi_get_cache_status(void)
-{
- return cache_status;
-}
-
-static int do_cbi_read(void)
-{
- CPRINTS("Reading board info");
-
- /* Read header */
- if (cbi_config.drv->load(0, cbi, sizeof(*head))) {
- CPRINTS("Failed to read header");
- return EC_ERROR_INVAL;
- }
-
- /* Check magic */
- if (memcmp(head->magic, cbi_magic, sizeof(head->magic))) {
- CPRINTS("Bad magic");
- return EC_ERROR_INVAL;
- }
-
- /* check version */
- if (head->major_version > CBI_VERSION_MAJOR) {
- CPRINTS("Version mismatch");
- return EC_ERROR_INVAL;
- }
-
- /*
- * Check the data size. It's expected to support up to 64k but our
- * buffer has practical limitation.
- */
- if (head->total_size < sizeof(*head) ||
- head->total_size > CBI_IMAGE_SIZE) {
- CPRINTS("Bad size: %d", head->total_size);
- return EC_ERROR_OVERFLOW;
- }
-
- /* Read the data */
- if (cbi_config.drv->load(sizeof(*head), head->data,
- head->total_size - sizeof(*head))) {
- CPRINTS("Failed to read body");
- return EC_ERROR_INVAL;
- }
-
- /* Check CRC. This supports new fields unknown to this parser. */
- if (cbi_config.storage_type != CBI_STORAGE_TYPE_GPIO &&
- cbi_crc8(head) != head->crc) {
- CPRINTS("Bad CRC");
- return EC_ERROR_INVAL;
- }
-
- return EC_SUCCESS;
-}
-
-static int cbi_read(void)
-{
- int i;
- int rv;
-
- if (cbi_get_cache_status() == CBI_CACHE_STATUS_SYNCED)
- return EC_SUCCESS;
-
- for (i = 0; i < 2; i++) {
- rv = do_cbi_read();
- if (rv == EC_SUCCESS) {
- cache_status = CBI_CACHE_STATUS_SYNCED;
- return EC_SUCCESS;
- }
- /* On error (I2C or bad contents), retry a read */
- }
-
- return rv;
-}
-
-__attribute__((weak))
-int cbi_board_override(enum cbi_data_tag tag, uint8_t *buf, uint8_t *size)
-{
- return EC_SUCCESS;
-}
-
-int cbi_get_board_info(enum cbi_data_tag tag, uint8_t *buf, uint8_t *size)
-{
- const struct cbi_data *d;
-
- if (cbi_read())
- return EC_ERROR_UNKNOWN;
-
- d = cbi_find_tag(cbi, tag);
- if (!d)
- /* Not found */
- return EC_ERROR_UNKNOWN;
- if (*size < d->size)
- /* Insufficient buffer size */
- return EC_ERROR_INVAL;
-
- /* Clear the buffer in case len < *size */
- memset(buf, 0, *size);
- /* Copy the value */
- memcpy(buf, d->value, d->size);
- *size = d->size;
-
- return cbi_board_override(tag, buf, size);
-}
-
-static void cbi_remove_tag(void *const cbi, struct cbi_data *const d)
-{
- struct cbi_header *const h = cbi;
- const size_t size = sizeof(*d) + d->size;
- const uint8_t *next = (uint8_t *)d + size;
- const size_t bytes_after = ((uint8_t *)cbi + h->total_size) - next;
-
- memmove(d, next, bytes_after);
- h->total_size -= size;
-}
-
-int cbi_set_board_info(enum cbi_data_tag tag, const uint8_t *buf, uint8_t size)
-{
- struct cbi_data *d;
-
- d = cbi_find_tag(cbi, tag);
-
- /* If we found the entry, but the size doesn't match, delete it */
- if (d && d->size != size) {
- cbi_remove_tag(cbi, d);
- d = NULL;
- }
-
- if (!d) {
- uint8_t *p;
- /* Not found. Check if new item would fit */
- if (sizeof(cbi) < head->total_size + sizeof(*d) + size)
- return EC_ERROR_OVERFLOW;
- /* Append new item */
- p = cbi_set_data(&cbi[head->total_size], tag, buf, size);
- head->total_size = p - cbi;
- } else {
- /* Overwrite existing item */
- memcpy(d->value, buf, d->size);
- }
-
- return EC_SUCCESS;
-}
-
-int cbi_write(void)
-{
- if (cbi_config.drv->is_protected()) {
- CPRINTS("Failed to write due to WP");
- return EC_ERROR_ACCESS_DENIED;
- }
-
- return cbi_config.drv->store(cbi);
-}
-
-int cbi_get_board_version(uint32_t *ver)
-{
- uint8_t size = sizeof(*ver);
-
- return cbi_get_board_info(CBI_TAG_BOARD_VERSION, (uint8_t *)ver, &size);
-}
-
-int cbi_get_sku_id(uint32_t *id)
-{
- uint8_t size = sizeof(*id);
-
- return cbi_get_board_info(CBI_TAG_SKU_ID, (uint8_t *)id, &size);
-}
-
-int cbi_get_oem_id(uint32_t *id)
-{
- uint8_t size = sizeof(*id);
-
- return cbi_get_board_info(CBI_TAG_OEM_ID, (uint8_t *)id, &size);
-}
-
-int cbi_get_model_id(uint32_t *id)
-{
- uint8_t size = sizeof(*id);
-
- return cbi_get_board_info(CBI_TAG_MODEL_ID, (uint8_t *)id, &size);
-}
-
-int cbi_get_fw_config(uint32_t *fw_config)
-{
- uint8_t size = sizeof(*fw_config);
-
- return cbi_get_board_info(CBI_TAG_FW_CONFIG, (uint8_t *)fw_config,
- &size);
-}
-
-int cbi_get_ssfc(uint32_t *ssfc)
-{
- uint8_t size = sizeof(*ssfc);
-
- return cbi_get_board_info(CBI_TAG_SSFC, (uint8_t *)ssfc,
- &size);
-}
-
-int cbi_get_pcb_supplier(uint32_t *pcb_supplier)
-{
- uint8_t size = sizeof(*pcb_supplier);
-
- return cbi_get_board_info(CBI_TAG_PCB_SUPPLIER, (uint8_t *)pcb_supplier,
- &size);
-}
-
-int cbi_get_rework_id(uint64_t *id)
-{
- uint8_t size = sizeof(*id);
- return cbi_get_board_info(CBI_TAG_REWORK_ID, (uint8_t *)id, &size);
-}
-
-static enum ec_status hc_cbi_get(struct host_cmd_handler_args *args)
-{
- const struct __ec_align4 ec_params_get_cbi *p = args->params;
- uint8_t size = MIN(args->response_max, UINT8_MAX);
-
- if (p->flag & CBI_GET_RELOAD)
- cbi_invalidate_cache();
-
- if (cbi_get_board_info(p->tag, args->response, &size))
- return EC_RES_INVALID_PARAM;
-
- args->response_size = size;
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_GET_CROS_BOARD_INFO,
- hc_cbi_get,
- EC_VER_MASK(0));
-
-static enum ec_status common_cbi_set(const struct __ec_align4
- ec_params_set_cbi * p)
-{
- /*
- * If we ultimately cannot write to the flash, then fail early unless
- * we are explicitly trying to write to the in-memory CBI only
- */
- if (cbi_config.drv->is_protected() &&
- !(p->flag & CBI_SET_NO_SYNC)) {
- CPRINTS("Failed to write due to WP");
- return EC_RES_ACCESS_DENIED;
- }
-
-#ifndef CONFIG_SYSTEM_UNLOCKED
- /*
- * These fields are not allowed to be reprogrammed regardless the
- * hardware WP state. They're considered as a part of the hardware.
- */
- if (p->tag == CBI_TAG_BOARD_VERSION || p->tag == CBI_TAG_OEM_ID)
- return EC_RES_ACCESS_DENIED;
-#endif
-
- if (p->flag & CBI_SET_INIT) {
- memset(cbi, 0, sizeof(cbi));
- memcpy(head->magic, cbi_magic, sizeof(cbi_magic));
- head->total_size = sizeof(*head);
- } else {
- if (cbi_read())
- return EC_RES_ERROR;
- }
-
- if (cbi_set_board_info(p->tag, p->data, p->size))
- return EC_RES_INVALID_PARAM;
-
- /*
- * Whether we're modifying existing data or creating new one,
- * we take over the format.
- */
- head->major_version = CBI_VERSION_MAJOR;
- head->minor_version = CBI_VERSION_MINOR;
- head->crc = cbi_crc8(head);
- cache_status = CBI_CACHE_STATUS_SYNCED;
-
- /* Skip write if client asks so. */
- if (p->flag & CBI_SET_NO_SYNC)
- return EC_RES_SUCCESS;
-
- /* We already checked write protect failure case. */
- if (cbi_write())
- return EC_RES_ERROR;
-
- return EC_RES_SUCCESS;
-}
-
-static enum ec_status hc_cbi_set(struct host_cmd_handler_args *args)
-{
- const struct __ec_align4 ec_params_set_cbi * p = args->params;
-
- /* Given data size exceeds the packet size. */
- if (args->params_size < sizeof(*p) + p->size)
- return EC_RES_INVALID_PARAM;
-
- return common_cbi_set(p);
-}
-DECLARE_HOST_COMMAND(EC_CMD_SET_CROS_BOARD_INFO,
- hc_cbi_set,
- EC_VER_MASK(0));
-
-#ifdef CONFIG_CMD_CBI
-static void print_tag(const char * const tag, int rv, const uint32_t *val)
-{
- ccprintf("%s", tag);
- if (rv == EC_SUCCESS && val)
- ccprintf(": %u (0x%x)\n", *val, *val);
- else
- ccprintf(": (Error %d)\n", rv);
-}
-
-static void print_uint64_tag(const char * const tag, int rv,
- const uint64_t *lval)
-{
- ccprintf("%s", tag);
- if (rv == EC_SUCCESS && lval)
- ccprintf(": %llu (0x%llx)\n", *(unsigned long long *)lval,
- *(unsigned long long *)lval);
- else
- ccprintf(": (Error %d)\n", rv);
-}
-
-static void dump_cbi(void)
-{
- uint32_t val;
- uint64_t lval;
-
- /* Ensure we read the latest data from flash. */
- cbi_invalidate_cache();
- cbi_read();
-
- if (cbi_get_cache_status() != CBI_CACHE_STATUS_SYNCED) {
- ccprintf("Cannot Read CBI (Error %d)\n", cbi_get_cache_status());
- return;
- }
-
- ccprintf("CBI_VERSION: 0x%04x\n", head->version);
- ccprintf("TOTAL_SIZE: %u\n", head->total_size);
-
- print_tag("BOARD_VERSION", cbi_get_board_version(&val), &val);
- print_tag("OEM_ID", cbi_get_oem_id(&val), &val);
- print_tag("MODEL_ID", cbi_get_model_id(&val), &val);
- print_tag("SKU_ID", cbi_get_sku_id(&val), &val);
- print_tag("FW_CONFIG", cbi_get_fw_config(&val), &val);
- print_tag("PCB_SUPPLIER", cbi_get_pcb_supplier(&val), &val);
- print_tag("SSFC", cbi_get_ssfc(&val), &val);
- print_uint64_tag("REWORK_ID", cbi_get_rework_id(&lval), &lval);
-}
-
-/*
- * Space for the set command (does not include data space) plus maximum
- * possible console input
- */
-static uint8_t buf[sizeof(struct ec_params_set_cbi) + \
- CONFIG_CONSOLE_INPUT_LINE_SIZE];
-
-static int cc_cbi(int argc, char **argv)
-{
- struct __ec_align4 ec_params_set_cbi * setter =
- (struct __ec_align4 ec_params_set_cbi *)buf;
- int last_arg;
- char *e;
-
- if (argc == 1) {
- dump_cbi();
- if (cbi_get_cache_status() == CBI_CACHE_STATUS_SYNCED)
- hexdump(cbi, CBI_IMAGE_SIZE);
- return EC_SUCCESS;
- }
-
- if (strcasecmp(argv[1], "set") == 0) {
- if (argc < 5) {
- ccprintf("Set requires: <tag> <value> <size>\n");
- return EC_ERROR_PARAM_COUNT;
- }
-
- setter->tag = strtoi(argv[2], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2;
-
- if (setter->tag == CBI_TAG_DRAM_PART_NUM ||
- setter->tag == CBI_TAG_OEM_NAME) {
- setter->size = strlen(argv[3]) + 1;
- memcpy(setter->data, argv[3], setter->size);
- } else {
- uint64_t val = strtoull(argv[3], &e, 0);
-
- if (*e)
- return EC_ERROR_PARAM3;
-
- setter->size = strtoi(argv[4], &e, 0);
- if (*e)
- return EC_ERROR_PARAM4;
-
- if (setter->size < 1) {
- ccprintf("Set size too small\n");
- return EC_ERROR_PARAM4;
- } else if (setter->tag == CBI_TAG_REWORK_ID &&
- setter->size > 8) {
- ccprintf("Set size too large\n");
- return EC_ERROR_PARAM4;
- } else if (setter->size > 4) {
- ccprintf("Set size too large\n");
- return EC_ERROR_PARAM4;
- }
-
- memcpy(setter->data, &val, setter->size);
- }
-
- last_arg = 5;
- } else if (strcasecmp(argv[1], "remove") == 0) {
- if (argc < 3) {
- ccprintf("Remove requires: <tag>\n");
- return EC_ERROR_PARAM_COUNT;
- }
-
- setter->tag = strtoi(argv[2], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2;
-
- setter->size = 0;
- last_arg = 3;
- } else {
- return EC_ERROR_PARAM1;
- }
-
- setter->flag = 0;
-
- if (argc > last_arg) {
- int i;
-
- for (i = last_arg; i < argc; i++) {
- if (strcasecmp(argv[i], "init") == 0) {
- setter->flag |= CBI_SET_INIT;
- } else if (strcasecmp(argv[i], "skip_write") == 0) {
- setter->flag |= CBI_SET_NO_SYNC;
- } else {
- ccprintf("Invalid additional option\n");
- return EC_ERROR_PARAM1 + i - 1;
- }
- }
- }
-
- if (common_cbi_set(setter) == EC_RES_SUCCESS)
- return EC_SUCCESS;
-
- return EC_ERROR_UNKNOWN;
-}
-DECLARE_CONSOLE_COMMAND(cbi, cc_cbi, "[set <tag> <value> <size> | "
- "remove <tag>] [init | skip_write]",
- "Print or change Cros Board Info from flash");
-#endif /* CONFIG_CMD_CBI */
-
-#ifndef HAS_TASK_CHIPSET
-int cbi_set_fw_config(uint32_t fw_config)
-{
- /* Check write protect status */
- if (cbi_config.drv->is_protected())
- return EC_ERROR_ACCESS_DENIED;
-
- /* Ensure that CBI has been configured */
- if (cbi_read())
- cbi_create();
-
- /* Update the FW_CONFIG field */
- cbi_set_board_info(CBI_TAG_FW_CONFIG, (uint8_t *)&fw_config,
- sizeof(int));
-
- /* Update CRC calculation and write to the storage */
- head->crc = cbi_crc8(head);
- if (cbi_write())
- return EC_ERROR_UNKNOWN;
-
- dump_cbi();
-
- return EC_SUCCESS;
-}
-#endif
-
-#endif /* !HOST_TOOLS_BUILD */
diff --git a/common/cbi_eeprom.c b/common/cbi_eeprom.c
deleted file mode 100644
index 2761f0b977..0000000000
--- a/common/cbi_eeprom.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* Copyright 2021 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.
- */
-
-/* Support Cros Board Info EEPROM */
-
-#include "console.h"
-#include "cros_board_info.h"
-#include "gpio.h"
-#include "i2c.h"
-#include "system.h"
-#include "timer.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_SYSTEM, "CBI " format, ## args)
-
-/*
- * We allow EEPROMs with page size of 8 or 16. Use 8 to be the most compatible.
- * This causes a little more overhead for writes, but we are not writing to the
- * EEPROM outside of the factory process.
- */
-#define EEPROM_PAGE_WRITE_SIZE 8
-#define EEPROM_PAGE_WRITE_MS 5
-
-static int eeprom_read(uint8_t offset, uint8_t *data, int len)
-{
- return i2c_read_block(I2C_PORT_EEPROM, I2C_ADDR_EEPROM_FLAGS,
- offset, data, len);
-}
-
-static int eeprom_is_write_protected(void)
-{
- if (IS_ENABLED(CONFIG_BYPASS_CBI_EEPROM_WP_CHECK))
- return 0;
-#if defined(CONFIG_WP_ACTIVE_HIGH)
- return gpio_get_level(GPIO_WP);
-#else
- return !gpio_get_level(GPIO_WP_L);
-#endif
-}
-
-static int eeprom_write(uint8_t *cbi)
-{
- uint8_t *p = cbi;
- int rest = ((struct cbi_header *)p)->total_size;
-
- while (rest > 0) {
- int size = MIN(EEPROM_PAGE_WRITE_SIZE, rest);
- int rv;
-
- rv = i2c_write_block(I2C_PORT_EEPROM, I2C_ADDR_EEPROM_FLAGS,
- p - cbi, p, size);
- if (rv) {
- CPRINTS("Failed to write for %d", rv);
- return rv;
- }
- /* Wait for internal write cycle completion */
- msleep(EEPROM_PAGE_WRITE_MS);
- p += size;
- rest -= size;
- }
-
- return EC_SUCCESS;
-}
-
-#ifdef CONFIG_EEPROM_CBI_WP
-void cbi_latch_eeprom_wp(void)
-{
- CPRINTS("WP latched");
- gpio_set_level(GPIO_EC_CBI_WP, 1);
-}
-#endif /* CONFIG_EEPROM_CBI_WP */
-
-const struct cbi_storage_driver eeprom_drv = {
- .store = eeprom_write,
- .load = eeprom_read,
- .is_protected = eeprom_is_write_protected,
-};
-
-const struct cbi_storage_config_t cbi_config = {
- .storage_type = CBI_STORAGE_TYPE_EEPROM,
- .drv = &eeprom_drv,
-};
diff --git a/common/cbi_gpio.c b/common/cbi_gpio.c
deleted file mode 100644
index 7b9fb25ebb..0000000000
--- a/common/cbi_gpio.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/* Copyright 2021 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.
- */
-
-/* Support Cros Board Info GPIO */
-
-#include "console.h"
-#include "cros_board_info.h"
-#include "gpio.h"
-#include "system.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_SYSTEM, "CBI " format, ## args)
-
-static int cbi_gpio_read(uint8_t offset, uint8_t *data, int len)
-{
- int board_id;
- int sku_id;
- int rv;
- int err = 0;
-
- if (cbi_get_cache_status() == CBI_CACHE_STATUS_SYNCED)
- return EC_SUCCESS;
-
- cbi_create();
-
- board_id = system_get_board_version();
- if (board_id < 0) {
- CPRINTS("Failed (%d) to get a valid board id", -board_id);
- err++;
- } else {
- rv = cbi_set_board_info(CBI_TAG_BOARD_VERSION,
- (uint8_t *)&board_id, sizeof(int));
- if (rv) {
- CPRINTS("Failed (%d) to set BOARD_VERSION tag", rv);
- err++;
- }
- }
-
- sku_id = system_get_sku_id();
- rv = cbi_set_board_info(CBI_TAG_SKU_ID,
- (uint8_t *)&sku_id, sizeof(int));
- if (rv) {
- CPRINTS("Failed (%d) to set SKU_ID tag", rv);
- err++;
- }
-
- if (err > 0)
- return EC_ERROR_UNKNOWN;
-
- return EC_SUCCESS;
-}
-
-static int cbi_gpio_is_write_protected(void)
-{
- /*
- * When CBI comes from strapping pins, any attempts for updating CBI
- * storage should be rejected.
- */
- return 1;
-}
-
-const struct cbi_storage_driver gpio_drv = {
- .load = cbi_gpio_read,
- .is_protected = cbi_gpio_is_write_protected,
-};
-
-const struct cbi_storage_config_t cbi_config = {
- .storage_type = CBI_STORAGE_TYPE_GPIO,
- .drv = &gpio_drv,
-};
diff --git a/common/cec.c b/common/cec.c
deleted file mode 100644
index 1bc3273c1d..0000000000
--- a/common/cec.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/* Copyright 2018 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.
- */
-
-#include "cec.h"
-#include "console.h"
-#include "task.h"
-
-#define CPRINTF(format, args...) cprintf(CC_CEC, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_CEC, format, ## args)
-
-/*
- * Mutex for the read-offset of the rx queue. Needed since the
- * queue is read and flushed from different contexts
- */
-static struct mutex rx_queue_readoffset_mutex;
-
-int cec_transfer_get_bit(const struct cec_msg_transfer *transfer)
-{
- if (transfer->byte >= MAX_CEC_MSG_LEN)
- return 0;
-
- return transfer->buf[transfer->byte] & (0x80 >> transfer->bit);
-}
-
-void cec_transfer_set_bit(struct cec_msg_transfer *transfer, int val)
-{
- uint8_t bit_flag;
-
- if (transfer->byte >= MAX_CEC_MSG_LEN)
- return;
- bit_flag = 0x80 >> transfer->bit;
- transfer->buf[transfer->byte] &= ~bit_flag;
- if (val)
- transfer->buf[transfer->byte] |= bit_flag;
-}
-
-void cec_transfer_inc_bit(struct cec_msg_transfer *transfer)
-{
- if (++(transfer->bit) == 8) {
- if (transfer->byte >= MAX_CEC_MSG_LEN)
- return;
- transfer->bit = 0;
- transfer->byte++;
- }
-}
-
-int cec_transfer_is_eom(const struct cec_msg_transfer *transfer, int len)
-{
- if (transfer->bit)
- return 0;
- return (transfer->byte == len);
-}
-
-void cec_rx_queue_flush(struct cec_rx_queue *queue)
-{
- mutex_lock(&rx_queue_readoffset_mutex);
- queue->read_offset = 0;
- mutex_unlock(&rx_queue_readoffset_mutex);
- queue->write_offset = 0;
-}
-
-int cec_rx_queue_push(struct cec_rx_queue *queue, const uint8_t *msg,
- uint8_t msg_len)
-{
- int i;
- uint32_t offset;
-
- if (msg_len > MAX_CEC_MSG_LEN || msg_len == 0)
- return EC_ERROR_INVAL;
-
- offset = queue->write_offset;
- /* Fill in message length last, if successful. Set to zero for now */
- queue->buf[offset] = 0;
- offset = (offset + 1) % CEC_RX_BUFFER_SIZE;
-
- for (i = 0 ; i < msg_len; i++) {
- if (offset == queue->read_offset) {
- /* Buffer full */
- return EC_ERROR_OVERFLOW;
- }
-
- queue->buf[offset] = msg[i];
- offset = (offset + 1) % CEC_RX_BUFFER_SIZE;
- }
-
- /*
- * Don't commit if we caught up with read-offset
- * since that would indicate an empty buffer
- */
- if (offset == queue->read_offset) {
- /* Buffer full */
- return EC_ERROR_OVERFLOW;
- }
-
- /* Commit the push */
- queue->buf[queue->write_offset] = msg_len;
- queue->write_offset = offset;
-
- return EC_SUCCESS;
-}
-
-int cec_rx_queue_pop(struct cec_rx_queue *queue, uint8_t *msg,
- uint8_t *msg_len)
-{
- int i;
-
- mutex_lock(&rx_queue_readoffset_mutex);
- if (queue->read_offset == queue->write_offset) {
- /* Queue empty */
- mutex_unlock(&rx_queue_readoffset_mutex);
- *msg_len = 0;
- return -1;
- }
-
- /* The first byte in the buffer is the message length */
- *msg_len = queue->buf[queue->read_offset];
- if (*msg_len == 0 || *msg_len > MAX_CEC_MSG_LEN) {
- mutex_unlock(&rx_queue_readoffset_mutex);
- *msg_len = 0;
- CPRINTF("Invalid CEC msg size: %u\n", *msg_len);
- return -1;
- }
-
- queue->read_offset = (queue->read_offset + 1) % CEC_RX_BUFFER_SIZE;
- for (i = 0; i < *msg_len; i++) {
- msg[i] = queue->buf[queue->read_offset];
- queue->read_offset = (queue->read_offset + 1) %
- CEC_RX_BUFFER_SIZE;
-
- }
-
- mutex_unlock(&rx_queue_readoffset_mutex);
-
- return 0;
-}
diff --git a/common/charge_manager.c b/common/charge_manager.c
deleted file mode 100644
index 862bb28725..0000000000
--- a/common/charge_manager.c
+++ /dev/null
@@ -1,1625 +0,0 @@
-/* Copyright 2014 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.
- */
-
-#include "adc.h"
-#include "atomic.h"
-#include "battery.h"
-#include "charge_manager.h"
-#include "charge_ramp.h"
-#include "charge_state_v2.h"
-#include "charger.h"
-#include "console.h"
-#include "dps.h"
-#include "extpower.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "system.h"
-#include "tcpm/tcpm.h"
-#include "timer.h"
-#include "usb_common.h"
-#include "usb_pd.h"
-#include "usb_pd_dpm.h"
-#include "usb_pd_tcpm.h"
-#include "util.h"
-
-#ifdef HAS_MOCK_CHARGE_MANAGER
-#error Mock defined HAS_MOCK_CHARGE_MANAGER
-#endif
-
-#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
-
-#define POWER(charge_port) ((charge_port.current) * (charge_port.voltage))
-
-/* Timeout for delayed override power swap, allow for 500ms extra */
-#define POWER_SWAP_TIMEOUT (PD_T_SRC_RECOVER_MAX + PD_T_SRC_TURN_ON + \
- PD_T_SAFE_0V + 500 * MSEC)
-
-/*
- * Default charge supplier priority
- *
- * - Always pick dedicated charge if present since that is the best product
- * decision.
- * - Pick PD negotiated chargers over everything else since they have the most
- * power potential and they may not currently be negotiated at a high power.
- * (and they can at least provide 15W)
- * - Pick Type-C which supplier current >= 1.5A, which has higher prioirty
- * than the BC1.2 and Type-C with current under 1.5A. (USB-C spec 1.3
- * Table 4-17: TYPEC 3.0A, 1.5A > BC1.2 > TYPEC under 1.5A)
- * - Then pick among the propreitary and BC1.2 chargers which ever has the
- * highest available power.
- * - Last, pick one from the rest suppliers. Also note that some boards assume
- * wireless suppliers as low priority.
- */
-__overridable const int supplier_priority[] = {
-#if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0
- [CHARGE_SUPPLIER_DEDICATED] = 0,
-#endif
- [CHARGE_SUPPLIER_PD] = 1,
- [CHARGE_SUPPLIER_TYPEC] = 2,
- [CHARGE_SUPPLIER_TYPEC_DTS] = 2,
-#ifdef CHARGE_MANAGER_BC12
- [CHARGE_SUPPLIER_PROPRIETARY] = 3,
- [CHARGE_SUPPLIER_BC12_DCP] = 3,
- [CHARGE_SUPPLIER_BC12_CDP] = 3,
- [CHARGE_SUPPLIER_BC12_SDP] = 3,
- [CHARGE_SUPPLIER_TYPEC_UNDER_1_5A] = 4,
- [CHARGE_SUPPLIER_OTHER] = 4,
- [CHARGE_SUPPLIER_VBUS] = 4,
-#endif
-#ifdef CONFIG_WIRELESS_CHARGER_P9221_R7
- [CHARGE_SUPPLIER_WPC_BPP] = 5,
- [CHARGE_SUPPLIER_WPC_EPP] = 5,
- [CHARGE_SUPPLIER_WPC_GPP] = 5,
-#endif
-
-};
-BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT);
-
-/* Keep track of available charge for each charge port. */
-static struct charge_port_info available_charge[CHARGE_SUPPLIER_COUNT]
- [CHARGE_PORT_COUNT];
-
-/* Keep track of when the supplier on each port is registered. */
-static timestamp_t registration_time[CHARGE_PORT_COUNT];
-
-/*
- * Charge current ceiling (mA) for ports. This can be set to temporarily limit
- * the charge pulled from a port, without influencing the port selection logic.
- * The ceiling can be set independently from several requestors, with the
- * minimum ceiling taking effect.
- */
-static int charge_ceil[CHARGE_PORT_COUNT][CEIL_REQUESTOR_COUNT];
-
-/* Dual-role capability of attached partner port */
-static enum dualrole_capabilities dualrole_capability[CHARGE_PORT_COUNT];
-
-#ifdef CONFIG_USB_PD_LOGGING
-/* Mark port as dirty when making changes, for later logging */
-static int save_log[CHARGE_PORT_COUNT];
-#endif
-
-/* Store current state of port enable / charge current. */
-static int charge_port = CHARGE_PORT_NONE;
-static int charge_current = CHARGE_CURRENT_UNINITIALIZED;
-static int charge_current_uncapped = CHARGE_CURRENT_UNINITIALIZED;
-static int charge_voltage;
-static int charge_supplier = CHARGE_SUPPLIER_NONE;
-static int override_port = OVERRIDE_OFF;
-
-static int delayed_override_port = OVERRIDE_OFF;
-static timestamp_t delayed_override_deadline;
-
-/* Source-out Rp values for TCPMv1 */
-__maybe_unused static uint8_t source_port_rp[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-#ifdef CONFIG_USB_PD_MAX_TOTAL_SOURCE_CURRENT
-/* 3A on one port and 1.5A on the rest */
-BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT * 1500 + 1500 <=
- CONFIG_USB_PD_MAX_TOTAL_SOURCE_CURRENT);
-#endif
-
-/*
- * charge_manager initially operates in safe mode until asked to leave (through
- * charge_manager_leave_safe_mode()). While in safe mode, the following
- * behavior is altered:
- *
- * 1) All chargers are considered dedicated (and thus are valid charge source
- * candidates) for the purpose of port selection.
- * 2) Charge ceilings are ignored. Most significantly, ILIM won't drop on PD
- * voltage transition. If current load is high during transition, some
- * chargers may brown-out.
- * 3) CHARGE_PORT_NONE will not be selected (POR default charge port will
- * remain selected rather than CHARGE_PORT_NONE).
- *
- * After leaving safe mode, charge_manager reverts to its normal behavior and
- * immediately selects charge port and current using standard rules.
- */
-#ifdef CONFIG_CHARGE_MANAGER_SAFE_MODE
-static int left_safe_mode;
-#else
-static const int left_safe_mode = 1;
-#endif
-
-enum charge_manager_change_type {
- CHANGE_CHARGE,
- CHANGE_DUALROLE,
-};
-
-static int is_pd_port(int port)
-{
- return port >= 0 && port < board_get_usb_pd_port_count();
-}
-
-static int is_sink(int port)
-{
- if (!is_pd_port(port))
- return board_charge_port_is_sink(port);
-
- return pd_get_power_role(port) == PD_ROLE_SINK;
-}
-
-/**
- * Some of the SKUs in certain boards have less number of USB PD ports than
- * defined in CONFIG_USB_PD_PORT_MAX_COUNT. With the charge port configuration
- * for DEDICATED_PORT towards the end, this will lead to holes in the static
- * configuration. The ports that fall in that hole are invalid and this function
- * is used to check the validity of the ports.
- */
-static int is_valid_port(int port)
-{
- if (port < 0 || port >= CHARGE_PORT_COUNT)
- return 0;
-
- /* Check if the port falls in the hole */
- if (port >= board_get_usb_pd_port_count() &&
- port < CONFIG_USB_PD_PORT_MAX_COUNT)
- return 0;
- return 1;
-}
-
-#ifndef TEST_BUILD
-static int is_connected(int port)
-{
- if (!is_pd_port(port))
- return board_charge_port_is_connected(port);
-
- return pd_is_connected(port);
-}
-#endif /* !TEST_BUILD */
-
-#ifndef CONFIG_CHARGE_MANAGER_DRP_CHARGING
-/**
- * In certain cases we need to override the default behavior of not charging
- * from non-dedicated chargers. If the system is in RO and locked, we have no
- * way of determining the actual dualrole capability of the charger because
- * PD communication is not allowed, so we must assume that it is dedicated.
- * Also, if no battery is present, the charger may be our only source of power,
- * so again we must assume that the charger is dedicated.
- *
- * @return 1 when we need to override the a non-dedicated charger
- * to be a dedicated one, 0 otherwise.
- */
-static int charge_manager_spoof_dualrole_capability(void)
-{
- return (system_get_image_copy() == EC_IMAGE_RO &&
- system_is_locked()) || !left_safe_mode;
-
-}
-#endif /* !CONFIG_CHARGE_MANAGER_DRP_CHARGING */
-
-/**
- * Initialize available charge. Run before board init, so board init can
- * initialize data, if needed.
- */
-static void charge_manager_init(void)
-{
- int i, j;
-
- for (i = 0; i < CHARGE_PORT_COUNT; ++i) {
- if (!is_valid_port(i))
- continue;
- for (j = 0; j < CHARGE_SUPPLIER_COUNT; ++j) {
- available_charge[j][i].current =
- CHARGE_CURRENT_UNINITIALIZED;
- available_charge[j][i].voltage =
- CHARGE_VOLTAGE_UNINITIALIZED;
- }
- for (j = 0; j < CEIL_REQUESTOR_COUNT; ++j)
- charge_ceil[i][j] = CHARGE_CEIL_NONE;
- if (!is_pd_port(i))
- dualrole_capability[i] = CAP_DEDICATED;
- if (is_pd_port(i) && !IS_ENABLED(CONFIG_USB_PD_TCPMV2))
- source_port_rp[i] = CONFIG_USB_PD_PULLUP;
- }
-}
-DECLARE_HOOK(HOOK_INIT, charge_manager_init, HOOK_PRIO_CHARGE_MANAGER_INIT);
-
-/**
- * Check if the charge manager is seeded.
- *
- * @return 1 if all ports/suppliers have reported
- * with some initial charge, 0 otherwise.
- */
-static int charge_manager_is_seeded(void)
-{
- /* Once we're seeded, we don't need to check again. */
- static int is_seeded;
- int i, j;
-
- if (is_seeded)
- return 1;
-
- for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i) {
- for (j = 0; j < CHARGE_PORT_COUNT; ++j) {
- if (!is_valid_port(j))
- continue;
- if (available_charge[i][j].current ==
- CHARGE_CURRENT_UNINITIALIZED ||
- available_charge[i][j].voltage ==
- CHARGE_VOLTAGE_UNINITIALIZED)
- return 0;
- }
- }
- is_seeded = 1;
- return 1;
-}
-
-#ifndef TEST_BUILD
-/**
- * Get the maximum charge current for a port.
- *
- * @param port Charge port.
- * @return Charge current (mA).
- */
-__maybe_unused static int charge_manager_get_source_current(int port)
-{
- if (!is_pd_port(port))
- return 0;
-
- switch (source_port_rp[port]) {
- case TYPEC_RP_3A0:
- return 3000;
- case TYPEC_RP_1A5:
- return 1500;
- case TYPEC_RP_USB:
- default:
- return 500;
- }
-}
-
-/*
- * Find a supplier considering available current, voltage, power, and priority.
- */
-static enum charge_supplier find_supplier(int port, enum charge_supplier sup,
- int min_cur)
-{
- int i;
- for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i) {
- if (available_charge[i][port].current <= min_cur ||
- available_charge[i][port].voltage <= 0)
- /* Doesn't meet volt or current requirement. Skip it. */
- continue;
- if (sup == CHARGE_SUPPLIER_NONE)
- /* Haven't found any yet. Take it unconditionally. */
- sup = i;
- else if (supplier_priority[sup] < supplier_priority[i])
- /* There is already a higher priority supplier. */
- continue;
- else if (supplier_priority[i] < supplier_priority[sup])
- /* This has a higher priority. Take it. */
- sup = i;
- else if (POWER(available_charge[i][port]) >
- POWER(available_charge[sup][port]))
- /* Priority is tie. Take it if power is higher. */
- sup = i;
- }
- return sup;
-}
-
-static enum charge_supplier get_current_supplier(int port)
-{
- enum charge_supplier supplier = CHARGE_SUPPLIER_NONE;
-
- /* Determine supplier information to show. */
- if (port == charge_port) {
- supplier = charge_supplier;
- } else {
- /* Consider available current */
- supplier = find_supplier(port, supplier, 0);
- if (supplier == CHARGE_SUPPLIER_NONE)
- /* Ignore available current */
- supplier = find_supplier(port, supplier, -1);
- }
-
- return supplier;
-}
-static enum usb_power_roles get_current_power_role(int port,
- enum charge_supplier supplier)
-{
- enum usb_power_roles role;
- if (charge_port == port)
- role = USB_PD_PORT_POWER_SINK;
- else if (is_connected(port) && !is_sink(port))
- role = USB_PD_PORT_POWER_SOURCE;
- else if (supplier != CHARGE_SUPPLIER_NONE)
- role = USB_PD_PORT_POWER_SINK_NOT_CHARGING;
- else
- role = USB_PD_PORT_POWER_DISCONNECTED;
- return role;
-}
-
-__overridable int board_get_vbus_voltage(int port)
-{
- return 0;
-}
-
-static int get_vbus_voltage(int port, enum usb_power_roles current_role)
-{
- int voltage_mv;
-
- /*
- * If we are sourcing power or sinking but not charging, then VBUS must
- * be 5V. If we are charging, then read VBUS ADC.
- */
- if (current_role == USB_PD_PORT_POWER_SINK_NOT_CHARGING) {
- voltage_mv = 5000;
- } else {
-#if defined(CONFIG_USB_PD_VBUS_MEASURE_CHARGER)
- /*
- * Try to get VBUS from the charger. If that fails, default to 0
- * mV.
- */
- if (charger_get_vbus_voltage(port, &voltage_mv))
- voltage_mv = 0;
-#elif defined(CONFIG_USB_PD_VBUS_MEASURE_TCPC)
- voltage_mv = tcpc_get_vbus_voltage(port);
-#elif defined(CONFIG_USB_PD_VBUS_MEASURE_ADC_EACH_PORT)
- voltage_mv = adc_read_channel(board_get_vbus_adc(port));
-#elif defined(CONFIG_USB_PD_VBUS_MEASURE_NOT_PRESENT)
- /* No VBUS ADC channel - voltage is unknown */
- voltage_mv = 0;
-#elif defined(CONFIG_USB_PD_VBUS_MEASURE_BY_BOARD)
- voltage_mv = board_get_vbus_voltage(port);
-#else
- /* There is a single ADC that measures joint Vbus */
- voltage_mv = adc_read_channel(ADC_VBUS);
-#endif
- }
- return voltage_mv;
-}
-
-int charge_manager_get_vbus_voltage(int port)
-{
- return get_vbus_voltage(port, get_current_power_role(port,
- get_current_supplier(port)));
-}
-
-/**
- * Fills passed power_info structure with current info about the passed port.
- *
- * @param port Charge port.
- * @param r USB PD power info to be updated.
- */
-static void charge_manager_fill_power_info(int port,
- struct ec_response_usb_pd_power_info *r)
-{
- enum charge_supplier sup = get_current_supplier(port);
-
- /* Fill in power role */
- r->role = get_current_power_role(port, sup);
-
- /* Is port partner dual-role capable */
- r->dualrole = (dualrole_capability[port] == CAP_DUALROLE);
-
- if (sup == CHARGE_SUPPLIER_NONE ||
- r->role == USB_PD_PORT_POWER_SOURCE) {
- if (is_pd_port(port)) {
- r->type = USB_CHG_TYPE_NONE;
- r->meas.voltage_max = 0;
- r->meas.voltage_now =
- r->role == USB_PD_PORT_POWER_SOURCE ? 5000 : 0;
- /* TCPMv2 tracks source-out current in the DPM */
- if (IS_ENABLED(CONFIG_USB_PD_TCPMV2))
- r->meas.current_max =
- dpm_get_source_current(port);
- else
- r->meas.current_max =
- charge_manager_get_source_current(port);
- r->max_power = 0;
- } else {
- r->type = USB_CHG_TYPE_NONE;
- board_fill_source_power_info(port, r);
- }
- } else {
- int use_ramp_current;
- switch (sup) {
- case CHARGE_SUPPLIER_PD:
- r->type = USB_CHG_TYPE_PD;
- break;
- case CHARGE_SUPPLIER_TYPEC:
- case CHARGE_SUPPLIER_TYPEC_DTS:
- r->type = USB_CHG_TYPE_C;
- break;
-#ifdef CHARGE_MANAGER_BC12
- case CHARGE_SUPPLIER_PROPRIETARY:
- r->type = USB_CHG_TYPE_PROPRIETARY;
- break;
- case CHARGE_SUPPLIER_BC12_DCP:
- r->type = USB_CHG_TYPE_BC12_DCP;
- break;
- case CHARGE_SUPPLIER_BC12_CDP:
- r->type = USB_CHG_TYPE_BC12_CDP;
- break;
- case CHARGE_SUPPLIER_BC12_SDP:
- r->type = USB_CHG_TYPE_BC12_SDP;
- break;
- case CHARGE_SUPPLIER_VBUS:
- r->type = USB_CHG_TYPE_VBUS;
- break;
-#endif
-#ifdef CONFIG_WIRELESS_CHARGER_P9221_R7
- /*
- * Todo:need kernel add wpc device node in power_supply
- * before that use USB_CHG_TYPE_PROPRIETARY to present WPC.
- */
- case CHARGE_SUPPLIER_WPC_BPP:
- case CHARGE_SUPPLIER_WPC_EPP:
- case CHARGE_SUPPLIER_WPC_GPP:
- r->type = USB_CHG_TYPE_PROPRIETARY;
- break;
-#endif
-#if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0
- case CHARGE_SUPPLIER_DEDICATED:
- r->type = USB_CHG_TYPE_DEDICATED;
- break;
-#endif
- default:
-#ifdef CONFIG_WIRELESS_CHARGER_P9221_R7
- r->type = USB_CHG_TYPE_VBUS;
-#else
- r->type = USB_CHG_TYPE_OTHER;
-#endif
- }
- r->meas.voltage_max = available_charge[sup][port].voltage;
-
- /*
- * Report unknown charger CHARGE_DETECT_DELAY after supplier
- * change since PD negotiation may take time.
- *
- * Do not debounce on batteryless systems because
- * USB_CHG_TYPE_UNKNOWN implies the system is still on battery
- * while some kind of negotiation happens, but by the time the
- * host might request this in a battery-free configuration we
- * must be stable (if not, the system is either up or about to
- * lose power again).
- */
-#ifdef CONFIG_BATTERY
- if (get_time().val < registration_time[port].val +
- CHARGE_DETECT_DELAY)
- r->type = USB_CHG_TYPE_UNKNOWN;
-#endif
-
-#if defined(HAS_TASK_CHG_RAMP) || defined(CONFIG_CHARGE_RAMP_HW)
- /* Read ramped current if active charging port */
- use_ramp_current =
- (charge_port == port) && chg_ramp_allowed(port, sup);
-#else
- use_ramp_current = 0;
-#endif
- if (use_ramp_current) {
- /* Current limit is output of ramp module */
- r->meas.current_lim = chg_ramp_get_current_limit();
-
- /*
- * If ramp is allowed, then the max current depends
- * on if ramp is stable. If ramp is stable, then
- * max current is same as input current limit. If
- * ramp is not stable, then we report the maximum
- * current we could ramp up to for this supplier.
- * If ramp is not allowed, max current is just the
- * available charge current.
- */
- r->meas.current_max = chg_ramp_is_stable() ?
- r->meas.current_lim : chg_ramp_max(port, sup,
- available_charge[sup][port].current);
-
- r->max_power =
- r->meas.current_max * r->meas.voltage_max;
- } else {
- r->meas.current_max = r->meas.current_lim =
- available_charge[sup][port].current;
- r->max_power = POWER(available_charge[sup][port]);
- }
-
- r->meas.voltage_now = get_vbus_voltage(port, r->role);
- }
-}
-#endif /* TEST_BUILD */
-
-#ifdef CONFIG_USB_PD_LOGGING
-/**
- * Saves a power state log entry with the current info about the passed port.
- */
-void charge_manager_save_log(int port)
-{
- uint16_t flags = 0;
- struct ec_response_usb_pd_power_info pinfo;
-
- if (!is_pd_port(port))
- return;
-
- save_log[port] = 0;
- charge_manager_fill_power_info(port, &pinfo);
-
- /* Flags are stored in the data field */
- if (port == override_port)
- flags |= CHARGE_FLAGS_OVERRIDE;
- if (port == delayed_override_port)
- flags |= CHARGE_FLAGS_DELAYED_OVERRIDE;
- flags |= pinfo.role | (pinfo.type << CHARGE_FLAGS_TYPE_SHIFT) |
- (pinfo.dualrole ? CHARGE_FLAGS_DUAL_ROLE : 0);
-
- pd_log_event(PD_EVENT_MCU_CHARGE,
- PD_LOG_PORT_SIZE(port, sizeof(pinfo.meas)),
- flags, &pinfo.meas);
-}
-#endif /* CONFIG_USB_PD_LOGGING */
-
-/**
- * Attempt to switch to power source on port if applicable.
- *
- * @param port USB-C port to be swapped.
- */
-static void charge_manager_switch_to_source(int port)
-{
- if (!is_pd_port(port))
- return;
-
- /* If connected to dual-role device, then ask for a swap */
- if (dualrole_capability[port] == CAP_DUALROLE && is_sink(port))
- pd_request_power_swap(port);
-}
-
-/**
- * Return the computed charge ceiling for a port, which represents the
- * minimum ceiling among all valid requestors.
- *
- * @param port Charge port.
- * @return Charge ceiling (mA) or CHARGE_CEIL_NONE.
- */
-static int charge_manager_get_ceil(int port)
-{
- int ceil = CHARGE_CEIL_NONE;
- int val, i;
-
- if (!is_valid_port(port))
- return ceil;
-
- for (i = 0; i < CEIL_REQUESTOR_COUNT; ++i) {
- val = charge_ceil[port][i];
- if (val != CHARGE_CEIL_NONE &&
- (ceil == CHARGE_CEIL_NONE || val < ceil))
- ceil = val;
- }
-
- return ceil;
-}
-
-/**
- * Select the 'best' charge port, as defined by the supplier heirarchy and the
- * ability of the port to provide power.
- *
- * @param new_port Pointer to the best charge port by definition.
- * @param new_supplier Pointer to the best charge supplier by definition.
- */
-static void charge_manager_get_best_charge_port(int *new_port,
- int *new_supplier)
-{
- int supplier = CHARGE_SUPPLIER_NONE;
- int port = CHARGE_PORT_NONE;
- int best_port_power = -1, candidate_port_power;
- int i, j;
-
- /* Skip port selection on OVERRIDE_DONT_CHARGE. */
- if (override_port != OVERRIDE_DONT_CHARGE) {
-
- /*
- * Charge supplier selection logic:
- * 1. Prefer DPS charge port.
- * 2. Prefer higher priority supply.
- * 3. Prefer higher power over lower in case priority is tied.
- * 4. Prefer current charge port over new port in case (1)
- * and (2) are tied.
- * available_charge can be changed at any time by other tasks,
- * so make no assumptions about its consistency.
- */
- for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i)
- for (j = 0; j < CHARGE_PORT_COUNT; ++j) {
- /* Skip this port if it is not valid. */
- if (!is_valid_port(j))
- continue;
-
- /*
- * Skip this supplier if there is no
- * available charge.
- */
- if (available_charge[i][j].current == 0 ||
- available_charge[i][j].voltage == 0)
- continue;
-
- /*
- * Don't select this port if we have a
- * charge on another override port.
- */
- if (override_port != OVERRIDE_OFF &&
- override_port == port &&
- override_port != j)
- continue;
-
-#ifndef CONFIG_CHARGE_MANAGER_DRP_CHARGING
- /*
- * Don't charge from a dual-role port unless
- * it is our override port.
- */
- if (dualrole_capability[j] != CAP_DEDICATED &&
- override_port != j &&
- !charge_manager_spoof_dualrole_capability())
- continue;
-#endif
-
- candidate_port_power =
- POWER(available_charge[i][j]);
-
- /* Select DPS port if provided. */
- if (IS_ENABLED(CONFIG_USB_PD_DPS) &&
- override_port == OVERRIDE_OFF &&
- i == CHARGE_SUPPLIER_PD &&
- j == dps_get_charge_port()) {
- supplier = i;
- port = j;
- break;
- /* Select if no supplier chosen yet. */
- } else if (supplier == CHARGE_SUPPLIER_NONE ||
- /* ..or if supplier priority is higher. */
- supplier_priority[i] <
- supplier_priority[supplier] ||
- /* ..or if this is our override port. */
- (j == override_port &&
- port != override_port) ||
- /* ..or if priority is tied and.. */
- (supplier_priority[i] ==
- supplier_priority[supplier] &&
- /* candidate port can supply more power or.. */
- (candidate_port_power > best_port_power ||
- /*
- * candidate port is the active port and can
- * supply the same amount of power.
- */
- (candidate_port_power == best_port_power &&
- charge_port == j)))) {
- supplier = i;
- port = j;
- best_port_power = candidate_port_power;
- }
- }
-
- }
-
-#ifdef CONFIG_BATTERY
- /*
- * if no battery present then retain same charge port
- * and charge supplier to avoid the port switching
- */
- if (charge_port != CHARGE_SUPPLIER_NONE &&
- charge_port != port &&
- (battery_is_present() == BP_NO ||
- (battery_is_present() == BP_YES &&
- battery_is_cut_off() != BATTERY_CUTOFF_STATE_NORMAL))) {
- port = charge_port;
- supplier = charge_supplier;
- }
-#endif
-
- *new_port = port;
- *new_supplier = supplier;
-}
-
-/**
- * Charge manager refresh -- responsible for selecting the active charge port
- * and charge power. Called as a deferred task.
- */
-static void charge_manager_refresh(void)
-{
- /* Always initialize charge port on first pass */
- static int active_charge_port_initialized;
- int new_supplier, new_port;
- int new_charge_current, new_charge_current_uncapped;
- int new_charge_voltage, i;
- int updated_new_port = CHARGE_PORT_NONE;
- int updated_old_port = CHARGE_PORT_NONE;
- int ceil;
- int power_changed = 0;
-
- /* Hunt for an acceptable charge port */
- while (1) {
- charge_manager_get_best_charge_port(&new_port, &new_supplier);
-
- if (!left_safe_mode && new_port == CHARGE_PORT_NONE)
- return;
-
- /*
- * If the port or supplier changed, make an attempt to switch to
- * the port. We will re-set the active port on a supplier change
- * to give the board-level function another chance to reject
- * the port, for example, if the port has become a charge
- * source.
- */
- if (active_charge_port_initialized &&
- new_port == charge_port &&
- new_supplier == charge_supplier)
- break;
-
- /*
- * For OCPC systems, reset the OCPC state to prevent current
- * spikes.
- */
- if (IS_ENABLED(CONFIG_OCPC)) {
- charge_set_active_chg_chip(new_port);
- trigger_ocpc_reset();
- }
-
- if (board_set_active_charge_port(new_port) == EC_SUCCESS) {
- if (IS_ENABLED(CONFIG_EXTPOWER))
- board_check_extpower();
- break;
- }
-
- /* 'Dont charge' request must be accepted. */
- ASSERT(new_port != CHARGE_PORT_NONE);
-
- /*
- * Zero the available charge on the rejected port so that
- * it is no longer chosen.
- */
- for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i) {
- available_charge[i][new_port].current = 0;
- available_charge[i][new_port].voltage = 0;
- }
- }
-
- active_charge_port_initialized = 1;
-
- /*
- * Clear override if it wasn't selected as the 'best' port -- it means
- * that no charge is available on the port, or the port was rejected.
- */
- if (override_port >= 0 && override_port != new_port)
- override_port = OVERRIDE_OFF;
-
- if (new_supplier == CHARGE_SUPPLIER_NONE) {
- new_charge_current = 0;
- new_charge_current_uncapped = 0;
- new_charge_voltage = 0;
- } else {
- new_charge_current_uncapped =
- available_charge[new_supplier][new_port].current;
-#ifdef CONFIG_CHARGE_RAMP_HW
- /*
- * Allow to set the maximum current value, so the hardware can
- * know the range of acceptable current values for its ramping.
- */
- if (chg_ramp_allowed(new_port, new_supplier))
- new_charge_current_uncapped =
- chg_ramp_max(new_port, new_supplier,
- new_charge_current_uncapped);
-#endif /* CONFIG_CHARGE_RAMP_HW */
- /* Enforce port charge ceiling. */
- ceil = charge_manager_get_ceil(new_port);
- if (left_safe_mode && ceil != CHARGE_CEIL_NONE)
- new_charge_current = MIN(ceil,
- new_charge_current_uncapped);
- else
- new_charge_current = new_charge_current_uncapped;
-
- new_charge_voltage =
- available_charge[new_supplier][new_port].voltage;
- }
-
- /* Change the charge limit + charge port/supplier if modified. */
- if (new_port != charge_port || new_charge_current != charge_current ||
- new_supplier != charge_supplier) {
-#ifdef HAS_TASK_CHG_RAMP
- chg_ramp_charge_supplier_change(
- new_port, new_supplier, new_charge_current,
- registration_time[new_port],
- new_charge_voltage);
-#else
-#ifdef CONFIG_CHARGE_RAMP_HW
- /* Enable or disable charge ramp */
- charger_set_hw_ramp(chg_ramp_allowed(new_port, new_supplier));
-#endif
- board_set_charge_limit(new_port, new_supplier,
- new_charge_current,
- new_charge_current_uncapped,
- new_charge_voltage);
-#endif /* HAS_TASK_CHG_RAMP */
-
- power_changed = 1;
-
- CPRINTS("CL: p%d s%d i%d v%d", new_port, new_supplier,
- new_charge_current, new_charge_voltage);
-
- /*
- * (b:192638664) We try to check AC OK again to avoid
- * unsuccessful detection in the initial detection.
- */
- if (IS_ENABLED(CONFIG_EXTPOWER))
- board_check_extpower();
- }
-
- /*
- * Signal new power request only if the port changed, the voltage
- * on the same port changed, or the actual uncapped current
- * on the same port changed (don't consider ceil).
- */
- if (new_port != CHARGE_PORT_NONE &&
- (new_port != charge_port ||
- new_charge_current_uncapped != charge_current_uncapped ||
- new_charge_voltage != charge_voltage))
- updated_new_port = new_port;
-
- /* If charge port changed, cleanup old port */
- if (charge_port != new_port && charge_port != CHARGE_PORT_NONE) {
- /* Check if need power swap */
- charge_manager_switch_to_source(charge_port);
- /* Signal new power request on old port */
- updated_old_port = charge_port;
- }
-
- /* Update globals to reflect current state. */
- charge_current = new_charge_current;
- charge_current_uncapped = new_charge_current_uncapped;
- charge_voltage = new_charge_voltage;
- charge_supplier = new_supplier;
- charge_port = new_port;
-
-#ifdef CONFIG_USB_PD_LOGGING
- /*
- * Write a log under the following conditions:
- * 1. A port becomes active or
- * 2. A port becomes inactive or
- * 3. The active charge port power limit changes or
- * 4. Any supplier change on an inactive port
- */
- if (updated_new_port != CHARGE_PORT_NONE)
- save_log[updated_new_port] = 1;
- /* Don't log non-meaningful changes on charge port */
- else if (charge_port != CHARGE_PORT_NONE)
- save_log[charge_port] = 0;
-
- if (updated_old_port != CHARGE_PORT_NONE)
- save_log[updated_old_port] = 1;
-
- for (i = 0; i < board_get_usb_pd_port_count(); ++i)
- if (save_log[i])
- charge_manager_save_log(i);
-#endif
-
- /* New power requests must be set only after updating the globals. */
- if (is_pd_port(updated_new_port)) {
- /* Check if we can get requested voltage/current */
- if ((IS_ENABLED(CONFIG_USB_PD_TCPMV1) &&
- IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE)) ||
- (IS_ENABLED(CONFIG_USB_PD_TCPMV2) &&
- IS_ENABLED(CONFIG_USB_PE_SM))) {
- uint32_t pdo;
- uint32_t max_voltage;
- uint32_t max_current;
- uint32_t unused;
- /*
- * Check if new voltage/current is different
- * than requested. If yes, send new power request
- */
- if (pd_get_requested_voltage(updated_new_port) !=
- charge_voltage ||
- pd_get_requested_current(updated_new_port) !=
- charge_current_uncapped)
- pd_set_new_power_request(updated_new_port);
-
- /*
- * Check if we can get more power from this port.
- * If yes, send new power request
- */
- pd_find_pdo_index(pd_get_src_cap_cnt(updated_new_port),
- pd_get_src_caps(updated_new_port),
- pd_get_max_voltage(), &pdo);
- pd_extract_pdo_power(pdo, &max_current, &max_voltage,
- &unused);
- if (charge_voltage != max_voltage ||
- charge_current_uncapped != max_current)
- pd_set_new_power_request(updated_new_port);
- } else {
- /*
- * Functions for getting requested voltage/current
- * are not available. Send new power request.
- */
- pd_set_new_power_request(updated_new_port);
- }
- }
- if (is_pd_port(updated_old_port))
- pd_set_new_power_request(updated_old_port);
-
- if (power_changed)
- /* notify host of power info change */
- pd_send_host_event(PD_EVENT_POWER_CHANGE);
-}
-DECLARE_DEFERRED(charge_manager_refresh);
-
-/**
- * Called when charge override times out waiting for power swap.
- */
-static void charge_override_timeout(void)
-{
- delayed_override_port = OVERRIDE_OFF;
- pd_send_host_event(PD_EVENT_POWER_CHANGE);
-}
-DECLARE_DEFERRED(charge_override_timeout);
-
-/**
- * Called CHARGE_DETECT_DELAY after the most recent charge change on a port.
- */
-static void charger_detect_debounced(void)
-{
- /* Inform host that charger detection is debounced. */
- pd_send_host_event(PD_EVENT_POWER_CHANGE);
-}
-DECLARE_DEFERRED(charger_detect_debounced);
-
-/**
- * Update charge parameters for a given port / supplier.
- *
- * @param change Type of change.
- * @param supplier Charge supplier to be updated.
- * @param port Charge port to be updated.
- * @param charge Charge port current / voltage.
- */
-static void charge_manager_make_change(enum charge_manager_change_type change,
- int supplier,
- int port,
- const struct charge_port_info *charge)
-{
- int i;
- int clear_override = 0;
-
- if (!is_valid_port(port)) {
- CPRINTS("%s: p%d invalid", __func__, port);
- return;
- }
-
- /* Determine if this is a change which can affect charge status */
- switch (change) {
- case CHANGE_CHARGE:
- /* Ignore changes where charge is identical */
- if (available_charge[supplier][port].current ==
- charge->current &&
- available_charge[supplier][port].voltage ==
- charge->voltage)
- return;
- if (charge->current > 0 &&
- available_charge[supplier][port].current == 0)
- clear_override = 1;
-#ifdef CONFIG_USB_PD_LOGGING
- save_log[port] = 1;
-#endif
- break;
- case CHANGE_DUALROLE:
- /*
- * Ignore all except for transition to non-dualrole,
- * which may occur some time after we see a charge
- */
-#ifndef CONFIG_CHARGE_MANAGER_DRP_CHARGING
- if (dualrole_capability[port] != CAP_DEDICATED)
-#endif
- return;
- /* Clear override only if a charge is present on the port */
- for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i)
- if (available_charge[i][port].current > 0) {
- clear_override = 1;
- break;
- }
- /*
- * If there is no charge present on the port, the dualrole
- * change is meaningless to charge_manager.
- */
- if (!clear_override)
- return;
- break;
- }
-
- /* Remove override when a charger is plugged */
- if (clear_override && override_port != port
-#ifndef CONFIG_CHARGE_MANAGER_DRP_CHARGING
- /* only remove override when it's a dedicated charger */
- && dualrole_capability[port] == CAP_DEDICATED
-#endif
- ) {
- override_port = OVERRIDE_OFF;
- if (delayed_override_port != OVERRIDE_OFF) {
- delayed_override_port = OVERRIDE_OFF;
- hook_call_deferred(&charge_override_timeout_data, -1);
- }
- }
-
- if (change == CHANGE_CHARGE) {
- available_charge[supplier][port].current = charge->current;
- available_charge[supplier][port].voltage = charge->voltage;
- registration_time[port] = get_time();
-
- /*
- * After CHARGE_DETECT_DELAY, inform the host that charger
- * detection has been debounced. Since only one deferred
- * routine exists for all ports, the deferred call for a given
- * port may potentially be cancelled. This is mostly harmless
- * since cancellation implies that PD_EVENT_POWER_CHANGE was
- * just sent due to the power change on another port.
- */
- if (charge->current > 0)
- hook_call_deferred(&charger_detect_debounced_data,
- CHARGE_DETECT_DELAY);
-
- /*
- * If we have a charge on our delayed override port within
- * the deadline, make it our override port.
- */
- if (port == delayed_override_port && charge->current > 0 &&
- is_sink(delayed_override_port) &&
- get_time().val < delayed_override_deadline.val) {
- delayed_override_port = OVERRIDE_OFF;
- hook_call_deferred(&charge_override_timeout_data, -1);
- charge_manager_set_override(port);
- }
- }
-
- /*
- * Don't call charge_manager_refresh unless all ports +
- * suppliers have reported in. We don't want to make changes
- * to our charge port until we are certain we know what is
- * attached.
- */
- if (charge_manager_is_seeded())
- hook_call_deferred(&charge_manager_refresh_data, 0);
-}
-
-void pd_set_input_current_limit(int port, uint32_t max_ma,
- uint32_t supply_voltage)
-{
- struct charge_port_info charge;
-
- if (IS_ENABLED(CONFIG_USB_PD_PREFER_MV))
- charge_reset_stable_current();
-
- charge.current = max_ma;
- charge.voltage = supply_voltage;
- charge_manager_update_charge(CHARGE_SUPPLIER_PD, port, &charge);
-}
-
-void typec_set_input_current_limit(int port, typec_current_t max_ma,
- uint32_t supply_voltage)
-{
- struct charge_port_info charge;
- int i;
- int supplier;
- int dts = !!(max_ma & TYPEC_CURRENT_DTS_MASK);
- static const enum charge_supplier typec_suppliers[] = {
- CHARGE_SUPPLIER_TYPEC,
- CHARGE_SUPPLIER_TYPEC_DTS,
-#ifdef CHARGE_MANAGER_BC12
- CHARGE_SUPPLIER_TYPEC_UNDER_1_5A,
-#endif /* CHARGE_MANAGER_BC12 */
- };
-
- charge.current = max_ma & TYPEC_CURRENT_ILIM_MASK;
- charge.voltage = supply_voltage;
-#if !defined(HAS_TASK_CHG_RAMP) && !defined(CONFIG_CHARGE_RAMP_HW)
- /*
- * DTS sources such as suzy-q may not be able to actually deliver
- * their advertised current, so limit it to reduce chance of OC,
- * if we can't ramp.
- */
- if (dts)
- charge.current = MIN(charge.current, 500);
-#endif
-
- supplier = dts ? CHARGE_SUPPLIER_TYPEC_DTS : CHARGE_SUPPLIER_TYPEC;
-
-#ifdef CHARGE_MANAGER_BC12
- /*
- * According to USB-C spec 1.3 Table 4-17 "Precedence of power source
- * usage", the priority should be: USB-C 3.0A, 1.5A > BC1.2 > USB-C
- * under 1.5A. Choosed the corresponding supplier type, according to
- * charge current, to update.
- */
- if (charge.current < 1500)
- supplier = CHARGE_SUPPLIER_TYPEC_UNDER_1_5A;
-#endif /* CHARGE_MANAGER_BC12 */
-
- charge_manager_update_charge(supplier, port, &charge);
-
- /*
- * TYPEC / TYPEC-DTS / TYPEC-UNDER_1_5A should be mutually exclusive.
- * Zero'ing all the other suppliers.
- */
- for (i = 0; i < ARRAY_SIZE(typec_suppliers); ++i)
- if (supplier != typec_suppliers[i])
- charge_manager_update_charge(typec_suppliers[i], port,
- NULL);
-}
-
-void charge_manager_update_charge(int supplier,
- int port,
- const struct charge_port_info *charge)
-{
- struct charge_port_info zero = {0};
- if (!charge)
- charge = &zero;
- charge_manager_make_change(CHANGE_CHARGE, supplier, port, charge);
-}
-
-void charge_manager_update_dualrole(int port, enum dualrole_capabilities cap)
-{
- if (!is_pd_port(port))
- return;
-
- /* Ignore when capability is unchanged */
- if (cap != dualrole_capability[port]) {
- dualrole_capability[port] = cap;
- charge_manager_make_change(CHANGE_DUALROLE, 0, port, NULL);
- }
-}
-
-#ifdef CONFIG_CHARGE_MANAGER_SAFE_MODE
-void charge_manager_leave_safe_mode(void)
-{
- if (left_safe_mode)
- return;
-
- CPRINTS("%s()", __func__);
- cflush();
- left_safe_mode = 1;
- if (charge_manager_is_seeded())
- hook_call_deferred(&charge_manager_refresh_data, 0);
-}
-#endif
-
-void charge_manager_set_ceil(int port, enum ceil_requestor requestor, int ceil)
-{
- if (!is_valid_port(port))
- return;
-
- if (charge_ceil[port][requestor] != ceil) {
- charge_ceil[port][requestor] = ceil;
- if (port == charge_port && charge_manager_is_seeded())
- hook_call_deferred(&charge_manager_refresh_data, 0);
- }
-}
-
-void charge_manager_force_ceil(int port, int ceil)
-{
- /*
- * Force our input current to ceil if we're exceeding it, without
- * waiting for our deferred task to run.
- */
- if (left_safe_mode && port == charge_port && ceil < charge_current)
- board_set_charge_limit(port, CHARGE_SUPPLIER_PD, ceil,
- charge_current_uncapped, charge_voltage);
-
- /*
- * Now inform charge_manager so it stays in sync with the state of
- * the world.
- */
- charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, ceil);
-}
-
-int charge_manager_set_override(int port)
-{
- int retval = EC_SUCCESS;
-
- CPRINTS("Charge Override: %d", port);
-
- /*
- * If attempting to change the override port, then return
- * error. Since we may be in the middle of a power swap on
- * the original override port, it's too complicated to
- * guarantee that the original override port is switched back
- * to source.
- */
- if (delayed_override_port != OVERRIDE_OFF)
- return EC_ERROR_BUSY;
-
- /* Set the override port if it's a sink. */
- if (port < 0 || is_sink(port)) {
- if (override_port != port) {
- override_port = port;
- if (charge_manager_is_seeded())
- hook_call_deferred(
- &charge_manager_refresh_data, 0);
- }
- }
- /*
- * If the attached device is capable of being a sink, request a
- * power swap and set the delayed override for swap completion.
- */
- else if (!is_sink(port) && dualrole_capability[port] == CAP_DUALROLE) {
- delayed_override_deadline.val = get_time().val +
- POWER_SWAP_TIMEOUT;
- delayed_override_port = port;
- hook_call_deferred(&charge_override_timeout_data,
- POWER_SWAP_TIMEOUT);
- pd_request_power_swap(port);
- /* Can't charge from requested port -- return error. */
- } else
- retval = EC_ERROR_INVAL;
-
- return retval;
-}
-
-int charge_manager_get_override(void)
-{
- return override_port;
-}
-
-int charge_manager_get_active_charge_port(void)
-{
- return charge_port;
-}
-
-int charge_manager_get_selected_charge_port(void)
-{
- int port, supplier;
-
- charge_manager_get_best_charge_port(&port, &supplier);
- return port;
-}
-
-int charge_manager_get_charger_current(void)
-{
- return charge_current;
-}
-
-int charge_manager_get_charger_voltage(void)
-{
- return charge_voltage;
-}
-
-enum charge_supplier charge_manager_get_supplier(void)
-{
- return charge_supplier;
-}
-
-int charge_manager_get_power_limit_uw(void)
-{
- int current_ma = charge_current;
- int voltage_mv = charge_voltage;
-
- if (current_ma == CHARGE_CURRENT_UNINITIALIZED ||
- voltage_mv == CHARGE_VOLTAGE_UNINITIALIZED)
- return 0;
- else
- return current_ma * voltage_mv;
-}
-
-#if defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) && \
- !defined(CONFIG_USB_PD_TCPMV2)
-/* Note: this functionality is a part of the TCPMv2 Device Poicy Manager */
-
-/* Bitmap of ports used as power source */
-static volatile uint32_t source_port_bitmap;
-BUILD_ASSERT(sizeof(source_port_bitmap)*8 >= CONFIG_USB_PD_PORT_MAX_COUNT);
-
-static inline int has_other_active_source(int port)
-{
- return source_port_bitmap & ~BIT(port);
-}
-
-static inline int is_active_source(int port)
-{
- return source_port_bitmap & BIT(port);
-}
-
-static int can_supply_max_current(int port)
-{
-#ifdef CONFIG_USB_PD_MAX_TOTAL_SOURCE_CURRENT
- /*
- * This guarantees active 3A source continues to supply 3A.
- *
- * Since redistribution occurs sequentially, younger ports get
- * priority. Priority surfaces only when 3A source is released.
- * That is, when 3A source is released, the youngest active
- * port gets 3A.
- */
- int p;
- if (!is_active_source(port))
- /* Non-active ports don't get 3A */
- return 0;
- for (p = 0; p < board_get_usb_pd_port_count(); p++) {
- if (p == port)
- continue;
- if (source_port_rp[p] ==
- CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT)
- return 0;
- }
- return 1;
-#else
- return is_active_source(port) && !has_other_active_source(port);
-#endif /* CONFIG_USB_PD_MAX_TOTAL_SOURCE_CURRENT */
-}
-
-void charge_manager_source_port(int port, int enable)
-{
- uint32_t prev_bitmap = source_port_bitmap;
- int p, rp;
-
- if (enable)
- atomic_or((uint32_t *)&source_port_bitmap, 1 << port);
- else
- atomic_clear_bits((uint32_t *)&source_port_bitmap, 1 << port);
-
- /* No change, exit early. */
- if (prev_bitmap == source_port_bitmap)
- return;
-
- /* Set port limit according to policy */
- for (p = 0; p < board_get_usb_pd_port_count(); p++) {
- rp = can_supply_max_current(p) ?
- CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT :
- CONFIG_USB_PD_PULLUP;
- source_port_rp[p] = rp;
-
-#ifdef CONFIG_USB_PD_LOGGING
- if (is_connected(p) && !is_sink(p))
- charge_manager_save_log(p);
-#endif
-
- typec_set_source_current_limit(p, rp);
- if (IS_ENABLED(CONFIG_USB_PD_TCPMV2))
- typec_select_src_current_limit_rp(p, rp);
- else
- tcpm_select_rp_value(p, rp);
- pd_update_contract(p);
- }
-}
-
-int charge_manager_get_source_pdo(const uint32_t **src_pdo, const int port)
-{
- if (can_supply_max_current(port)) {
- *src_pdo = pd_src_pdo_max;
- return pd_src_pdo_max_cnt;
- }
-
- *src_pdo = pd_src_pdo;
- return pd_src_pdo_cnt;
-}
-#endif /* CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT && !CONFIG_USB_PD_TCPMV2 */
-
-#ifndef TEST_BUILD
-static enum ec_status hc_pd_power_info(struct host_cmd_handler_args *args)
-{
- const struct ec_params_usb_pd_power_info *p = args->params;
- struct ec_response_usb_pd_power_info *r = args->response;
- int port = p->port;
-
- /* If host is asking for the charging port, set port appropriately */
- if (port == PD_POWER_CHARGING_PORT)
- port = charge_port;
-
- /*
- * Not checking for invalid port here, because it might break existing
- * contract with ectool users. The invalid ports will have the response
- * voltage, current and power parameters set to 0.
- */
- if (port >= CHARGE_PORT_COUNT)
- return EC_RES_INVALID_PARAM;
-
- charge_manager_fill_power_info(port, r);
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_POWER_INFO,
- hc_pd_power_info,
- EC_VER_MASK(0));
-#endif /* TEST_BUILD */
-
-static enum ec_status hc_charge_port_count(struct host_cmd_handler_args *args)
-{
- struct ec_response_charge_port_count *resp = args->response;
-
- args->response_size = sizeof(*resp);
- resp->port_count = CHARGE_PORT_COUNT;
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_CHARGE_PORT_COUNT,
- hc_charge_port_count,
- EC_VER_MASK(0));
-
-static enum ec_status
-hc_charge_port_override(struct host_cmd_handler_args *args)
-{
- const struct ec_params_charge_port_override *p = args->params;
- const int16_t override_port = p->override_port;
-
- if (override_port < OVERRIDE_DONT_CHARGE ||
- override_port >= CHARGE_PORT_COUNT)
- return EC_RES_INVALID_PARAM;
-
- return charge_manager_set_override(override_port) == EC_SUCCESS ?
- EC_RES_SUCCESS : EC_RES_ERROR;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PD_CHARGE_PORT_OVERRIDE,
- hc_charge_port_override,
- EC_VER_MASK(0));
-
-#if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0
-static enum ec_status hc_override_dedicated_charger_limit(
- struct host_cmd_handler_args *args)
-{
- const struct ec_params_dedicated_charger_limit *p = args->params;
- struct charge_port_info ci = {
- .current = p->current_lim,
- .voltage = p->voltage_lim,
- };
-
- /*
- * Allow a change only if the dedicated charge port is used. Host needs
- * to apply a change every time a dedicated charger is plugged.
- */
- if (charge_port != DEDICATED_CHARGE_PORT)
- return EC_RES_UNAVAILABLE;
-
- charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED,
- DEDICATED_CHARGE_PORT, &ci);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_OVERRIDE_DEDICATED_CHARGER_LIMIT,
- hc_override_dedicated_charger_limit,
- EC_VER_MASK(0));
-#endif
-
-static int command_charge_port_override(int argc, char **argv)
-{
- int port = OVERRIDE_OFF;
- int ret = EC_SUCCESS;
- char *e;
-
- if (argc >= 2) {
- port = strtoi(argv[1], &e, 0);
- if (*e || port < OVERRIDE_DONT_CHARGE ||
- port >= CHARGE_PORT_COUNT)
- return EC_ERROR_PARAM1;
- ret = charge_manager_set_override(port);
- }
-
- ccprintf("Override: %d\n", (argc >= 2 && ret == EC_SUCCESS) ?
- port : override_port);
- return ret;
-}
-DECLARE_CONSOLE_COMMAND(chgoverride, command_charge_port_override,
- "[port | -1 | -2]",
- "Force charging from a given port (-1 = off, -2 = disable charging)");
-
-#ifdef CONFIG_CHARGE_MANAGER_EXTERNAL_POWER_LIMIT
-static void charge_manager_set_external_power_limit(int current_lim,
- int voltage_lim)
-{
- int port;
-
- if (current_lim == EC_POWER_LIMIT_NONE)
- current_lim = CHARGE_CEIL_NONE;
- if (voltage_lim == EC_POWER_LIMIT_NONE)
- voltage_lim = PD_MAX_VOLTAGE_MV;
-
- for (port = 0; port < board_get_usb_pd_port_count(); ++port) {
- charge_manager_set_ceil(port, CEIL_REQUESTOR_HOST, current_lim);
- pd_set_external_voltage_limit(port, voltage_lim);
- }
-}
-
-/*
- * On transition out of S0, disable all external power limits, in case AP
- * failed to clear them.
- */
-static void charge_manager_external_power_limit_off(void)
-{
- charge_manager_set_external_power_limit(EC_POWER_LIMIT_NONE,
- EC_POWER_LIMIT_NONE);
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, charge_manager_external_power_limit_off,
- HOOK_PRIO_DEFAULT);
-
-static enum ec_status
-hc_external_power_limit(struct host_cmd_handler_args *args)
-{
- const struct ec_params_external_power_limit_v1 *p = args->params;
-
- charge_manager_set_external_power_limit(p->current_lim,
- p->voltage_lim);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_EXTERNAL_POWER_LIMIT,
- hc_external_power_limit,
- EC_VER_MASK(1));
-
-static int command_external_power_limit(int argc, char **argv)
-{
- int max_current;
- int max_voltage;
- char *e;
-
- if (argc >= 2) {
- max_current = strtoi(argv[1], &e, 10);
- if (*e)
- return EC_ERROR_PARAM1;
- } else
- max_current = EC_POWER_LIMIT_NONE;
-
- if (argc >= 3) {
- max_voltage = strtoi(argv[2], &e, 10);
- if (*e)
- return EC_ERROR_PARAM1;
- } else
- max_voltage = EC_POWER_LIMIT_NONE;
-
- charge_manager_set_external_power_limit(max_current, max_voltage);
- ccprintf("max req: %dmA %dmV\n", max_current, max_voltage);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(chglim, command_external_power_limit,
- "[max_current (mA)] [max_voltage (mV)]",
- "Set max charger current / voltage");
-#endif /* CONFIG_CHARGE_MANAGER_EXTERNAL_POWER_LIMIT */
-
-#ifdef CONFIG_CMD_CHARGE_SUPPLIER_INFO
-static int charge_supplier_info(int argc, char **argv)
-{
- ccprintf("port=%d, type=%d, cur=%dmA, vtg=%dmV, lsm=%d\n",
- charge_manager_get_active_charge_port(),
- charge_supplier,
- charge_current,
- charge_voltage,
- left_safe_mode);
-
- return 0;
-}
-DECLARE_CONSOLE_COMMAND(chgsup, charge_supplier_info,
- NULL, "print chg supplier info");
-#endif
-
-__overridable
-int board_charge_port_is_sink(int port)
-{
- return 1;
-}
-
-__overridable
-int board_charge_port_is_connected(int port)
-{
- return 1;
-}
-
-__overridable
-void board_fill_source_power_info(int port,
- struct ec_response_usb_pd_power_info *r)
-{
- r->meas.voltage_now = 0;
- r->meas.voltage_max = 0;
- r->meas.current_max = 0;
- r->meas.current_lim = 0;
- r->max_power = 0;
-}
diff --git a/common/charge_ramp.c b/common/charge_ramp.c
deleted file mode 100644
index a408771f40..0000000000
--- a/common/charge_ramp.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Copyright 2017 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.
- */
-
-/* Charge input current limit ramp module for Chrome EC */
-
-#include "charge_manager.h"
-#include "common.h"
-#include "system.h"
-#include "usb_charge.h"
-#include "util.h"
-
-test_mockable int chg_ramp_allowed(int port, int supplier)
-{
- /* Don't allow ramping in RO when write protected. */
- if (!system_is_in_rw() && system_is_locked())
- return 0;
-
- switch (supplier) {
- /* Use ramping for USB-C DTS suppliers (debug accessory eg suzy-q). */
- 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).
- */
- case CHARGE_SUPPLIER_PD:
- case CHARGE_SUPPLIER_TYPEC:
- return IS_ENABLED(CONFIG_CHARGE_RAMP_HW);
- /* default: fall through */
- }
-
- /* Otherwise ask the BC1.2 detect module */
- return usb_charger_ramp_allowed(port, supplier);
-}
-
-test_mockable int chg_ramp_max(int port, int supplier, int sup_curr)
-{
- switch (supplier) {
- case CHARGE_SUPPLIER_PD:
- case CHARGE_SUPPLIER_TYPEC:
- case CHARGE_SUPPLIER_TYPEC_DTS:
- /*
- * We should not ramp DTS beyond what they advertise, otherwise
- * we may brownout the systems they are connected to.
- */
- return sup_curr;
- /* default: fall through */
- }
-
- /* Otherwise ask the BC1.2 detect module */
- return usb_charger_ramp_max(port, supplier, sup_curr);
-}
diff --git a/common/charge_ramp_sw.c b/common/charge_ramp_sw.c
deleted file mode 100644
index bfd6db057b..0000000000
--- a/common/charge_ramp_sw.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/* Copyright 2017 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.
- */
-
-/* Charge input current limit ramp module for Chrome EC */
-
-#include "charge_manager.h"
-#include "charge_ramp.h"
-#include "charge_state.h"
-#include "common.h"
-#include "console.h"
-#include "ec_commands.h"
-#include "task.h"
-#include "timer.h"
-#include "usb_pd.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
-
-/* Number of times to ramp current searching for limit before stable charging */
-#define RAMP_COUNT 3
-
-/* Maximum allowable time charger can be unplugged to be considered an OCP */
-#define OC_RECOVER_MAX_TIME (SECOND)
-
-/* Delay for running state machine when board is not consuming full current */
-#define CURRENT_DRAW_DELAY (5*SECOND)
-
-/* Current ramp increment */
-#define RAMP_CURR_INCR_MA 64
-#define RAMP_CURR_DELAY (500*MSEC)
-#define RAMP_CURR_START_MA 500
-
-/* How much to backoff the input current limit when limit has been found */
-#define RAMP_ICL_BACKOFF (2*RAMP_CURR_INCR_MA)
-
-/* Interval at which VBUS voltage is monitored in stable state */
-#define STABLE_VBUS_MONITOR_INTERVAL (SECOND)
-
-/* Time to delay for stablizing the charging current */
-#define STABLIZE_DELAY (5*SECOND)
-
-enum chg_ramp_state {
- CHG_RAMP_DISCONNECTED,
- CHG_RAMP_CHARGE_DETECT_DELAY,
- CHG_RAMP_OVERCURRENT_DETECT,
- CHG_RAMP_RAMP,
- CHG_RAMP_STABILIZE,
- CHG_RAMP_STABLE,
-};
-static enum chg_ramp_state ramp_st;
-
-struct oc_info {
- timestamp_t ts;
- int oc_detected;
- int sup;
- int icl;
-};
-
-/* OCP info for each over-current */
-static struct oc_info oc_info[CONFIG_USB_PD_PORT_MAX_COUNT][RAMP_COUNT];
-static int oc_info_idx[CONFIG_USB_PD_PORT_MAX_COUNT];
-#define ACTIVE_OC_INFO (oc_info[active_port][oc_info_idx[active_port]])
-
-/* Active charging information */
-static int active_port = CHARGE_PORT_NONE;
-static int active_sup;
-static int active_icl;
-static int active_vtg;
-static timestamp_t reg_time;
-
-static int stablize_port;
-static int stablize_sup;
-
-/* Maximum/minimum input current limit for active charger */
-static int max_icl;
-static int min_icl;
-
-void chg_ramp_charge_supplier_change(int port, int supplier, int current,
- timestamp_t registration_time, int voltage)
-{
- /*
- * If the last active port was a valid port and the port
- * has changed, then this may have been an over-current.
- */
- if (active_port != CHARGE_PORT_NONE &&
- port != active_port) {
- if (oc_info_idx[active_port] == RAMP_COUNT - 1)
- oc_info_idx[active_port] = 0;
- else
- oc_info_idx[active_port]++;
- ACTIVE_OC_INFO.ts = get_time();
- ACTIVE_OC_INFO.sup = active_sup;
- ACTIVE_OC_INFO.icl = active_icl;
- }
-
- /* Set new active port, set ramp state, and wake ramp task */
- active_port = port;
- active_sup = supplier;
- active_vtg = voltage;
-
- /* Set min and max input current limit based on if ramp is allowed */
- if (chg_ramp_allowed(active_port, active_sup)) {
- min_icl = RAMP_CURR_START_MA;
- max_icl = chg_ramp_max(active_port, active_sup, current);
- } else {
- min_icl = max_icl = current;
- }
-
- reg_time = registration_time;
- if (ramp_st != CHG_RAMP_STABILIZE) {
- ramp_st = (active_port == CHARGE_PORT_NONE) ?
- CHG_RAMP_DISCONNECTED : CHG_RAMP_CHARGE_DETECT_DELAY;
- CPRINTS("Ramp reset: st%d", ramp_st);
- task_wake(TASK_ID_CHG_RAMP);
- }
-}
-
-int chg_ramp_get_current_limit(void)
-{
- /*
- * If we are ramping or stable, then use the active input
- * current limit. Otherwise, use the minimum input current
- * limit.
- */
- switch (ramp_st) {
- case CHG_RAMP_RAMP:
- case CHG_RAMP_STABILIZE:
- case CHG_RAMP_STABLE:
- return active_icl;
- default:
- return min_icl;
- }
-}
-
-int chg_ramp_is_detected(void)
-{
- /* Charger detected (charge detect delay has passed) */
- return ramp_st > CHG_RAMP_CHARGE_DETECT_DELAY;
-}
-
-int chg_ramp_is_stable(void)
-{
- return ramp_st == CHG_RAMP_STABLE;
-}
-
-void chg_ramp_task(void *u)
-{
- int task_wait_time = -1;
- int i, lim;
- uint64_t detect_end_time_us = 0, time_us;
- int last_active_port = CHARGE_PORT_NONE;
-
- enum chg_ramp_state ramp_st_prev = CHG_RAMP_DISCONNECTED,
- ramp_st_new = CHG_RAMP_DISCONNECTED;
- int active_icl_new;
-
- /* Clear last OCP supplier to guarantee we ramp on first connect */
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- oc_info[i][0].sup = CHARGE_SUPPLIER_NONE;
-
- /*
- * Sleep until chg_ramp_charge_supplier_change is called to avoid
- * setting input current limit to zero. chg_ramp_charge_supplier_change
- * won't be called until charge_manager is ready to call
- * board_set_charge_limit by itself (if there is no chg_ramp_task).
- */
- if (!IS_ENABLED(TEST_BUILD))
- task_wait_event(-1);
-
- while (1) {
- ramp_st_new = ramp_st;
- active_icl_new = active_icl;
- switch (ramp_st) {
- case CHG_RAMP_DISCONNECTED:
- /* Do nothing */
- task_wait_time = -1;
- break;
- case CHG_RAMP_CHARGE_DETECT_DELAY:
- /* Delay for charge_manager to determine supplier */
- /*
- * On entry to state, or if port changes, check
- * timestamps to determine if this was likely an
- * OC event (check if we lost VBUS and it came back
- * within OC_RECOVER_MAX_TIME).
- */
- if (ramp_st_prev != ramp_st ||
- active_port != last_active_port) {
- last_active_port = active_port;
- if (reg_time.val <
- ACTIVE_OC_INFO.ts.val +
- OC_RECOVER_MAX_TIME) {
- ACTIVE_OC_INFO.oc_detected = 1;
- } else {
- for (i = 0; i < RAMP_COUNT; ++i)
- oc_info[active_port][i].
- oc_detected = 0;
- }
- detect_end_time_us = get_time().val +
- CHARGE_DETECT_DELAY;
- task_wait_time = CHARGE_DETECT_DELAY;
- break;
- }
-
- /* If detect delay has not passed, set wait time */
- time_us = get_time().val;
- if (time_us < detect_end_time_us) {
- task_wait_time = detect_end_time_us - time_us;
- break;
- }
-
- /* Detect delay is over, fall through to next state */
- ramp_st_new = CHG_RAMP_OVERCURRENT_DETECT;
- /* notify host of power info change */
- pd_send_host_event(PD_EVENT_POWER_CHANGE);
- case CHG_RAMP_OVERCURRENT_DETECT:
- /* Check if we should ramp or go straight to stable */
- task_wait_time = SECOND;
-
- /* Skip ramp for specific suppliers */
- if (!chg_ramp_allowed(active_port, active_sup)) {
- active_icl_new = min_icl;
- ramp_st_new = CHG_RAMP_STABLE;
- break;
- }
-
- /*
- * If we are not drawing full charge, then don't ramp,
- * just wait in this state, until we are.
- */
- if (!charge_is_consuming_full_input_current()) {
- task_wait_time = CURRENT_DRAW_DELAY;
- break;
- }
-
- /*
- * Compare recent OCP events, if all info matches,
- * then we don't need to ramp anymore.
- */
- for (i = 0; i < RAMP_COUNT; i++) {
- if (oc_info[active_port][i].sup != active_sup ||
- !oc_info[active_port][i].oc_detected)
- break;
- }
-
- if (i == RAMP_COUNT) {
- /* Found OC threshold! */
- active_icl_new = ACTIVE_OC_INFO.icl -
- RAMP_ICL_BACKOFF;
- ramp_st_new = CHG_RAMP_STABLE;
- } else {
- /*
- * Need to ramp to find OC threshold, start
- * at the minimum input current limit.
- */
- active_icl_new = min_icl;
- ramp_st_new = CHG_RAMP_RAMP;
- }
- break;
- case CHG_RAMP_RAMP:
- /* Keep ramping until we find the limit */
- task_wait_time = RAMP_CURR_DELAY;
-
- /* Pause ramping if we are not drawing full current */
- if (!charge_is_consuming_full_input_current()) {
- task_wait_time = CURRENT_DRAW_DELAY;
- break;
- }
-
- /* If VBUS is sagging a lot, then stop ramping */
- if (board_is_vbus_too_low(active_port,
- CHG_RAMP_VBUS_RAMPING)) {
- CPRINTS("VBUS low");
- active_icl_new = MAX(min_icl, active_icl -
- RAMP_ICL_BACKOFF);
- ramp_st_new = CHG_RAMP_STABILIZE;
- task_wait_time = STABLIZE_DELAY;
- stablize_port = active_port;
- stablize_sup = active_sup;
- break;
- }
-
- /* Ramp the current limit if we haven't reached max */
- if (active_icl == max_icl)
- ramp_st_new = CHG_RAMP_STABLE;
- else if (active_icl + RAMP_CURR_INCR_MA > max_icl)
- active_icl_new = max_icl;
- else
- active_icl_new = active_icl + RAMP_CURR_INCR_MA;
- break;
- case CHG_RAMP_STABILIZE:
- /* Wait for current to stabilize after ramp is done */
- /* Use default delay for exiting this state */
- task_wait_time = SECOND;
- if (active_port == stablize_port &&
- active_sup == stablize_sup) {
- ramp_st_new = CHG_RAMP_STABLE;
- break;
- }
-
- ramp_st_new = active_port == CHARGE_PORT_NONE ?
- CHG_RAMP_DISCONNECTED :
- CHG_RAMP_CHARGE_DETECT_DELAY;
- break;
- case CHG_RAMP_STABLE:
- /* Maintain input current limit */
- /* On entry log charging stats */
- if (ramp_st_prev != ramp_st) {
-#ifdef CONFIG_USB_PD_LOGGING
- charge_manager_save_log(active_port);
-#endif
- /* notify host of power info change */
- pd_send_host_event(PD_EVENT_POWER_CHANGE);
- }
-
- /* Keep an eye on VBUS and restart ramping if it dips */
- if (chg_ramp_allowed(active_port, active_sup) &&
- board_is_vbus_too_low(active_port,
- CHG_RAMP_VBUS_STABLE)) {
- CPRINTS("VBUS low; Re-ramp");
- max_icl = MAX(min_icl,
- max_icl - RAMP_ICL_BACKOFF);
- active_icl_new = min_icl;
- ramp_st_new = CHG_RAMP_RAMP;
- }
- task_wait_time = STABLE_VBUS_MONITOR_INTERVAL;
- break;
- }
-
- ramp_st_prev = ramp_st;
- ramp_st = ramp_st_new;
- active_icl = active_icl_new;
-
- /* Skip setting limit if status is stable twice in a row */
- if (ramp_st_prev != CHG_RAMP_STABLE ||
- ramp_st != CHG_RAMP_STABLE) {
- CPRINTS("Ramp p%d st%d %dmA %dmA",
- active_port, ramp_st, min_icl, active_icl);
- /* Set the input current limit */
- lim = chg_ramp_get_current_limit();
- board_set_charge_limit(active_port, active_sup, lim,
- lim, active_vtg);
- }
-
- if (ramp_st == CHG_RAMP_STABILIZE)
- /*
- * When in stabilize state, supplier/port may change
- * and we don't want to wake up task until we have
- * slept this amount of time.
- */
- usleep(task_wait_time);
- else
- task_wait_event(task_wait_time);
- }
-}
-
-#ifdef CONFIG_CMD_CHGRAMP
-static int command_chgramp(int argc, char **argv)
-{
- int i;
- int port;
-
- ccprintf("Chg Ramp:\nState: %d\nMin ICL: %d\nActive ICL: %d\n",
- ramp_st, min_icl, active_icl);
-
- for (port = 0; port < board_get_usb_pd_port_count(); port++) {
- ccprintf("Port %d:\n", port);
- ccprintf(" OC idx:%d\n", oc_info_idx[port]);
- for (i = 0; i < RAMP_COUNT; i++) {
- ccprintf(" OC %d: s%d oc_det%d icl%d\n", i,
- oc_info[port][i].sup,
- oc_info[port][i].oc_detected,
- oc_info[port][i].icl);
- }
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(chgramp, command_chgramp,
- "",
- "Dump charge ramp state info");
-#endif
diff --git a/common/charge_state_v2.c b/common/charge_state_v2.c
deleted file mode 100644
index 110d63c7bf..0000000000
--- a/common/charge_state_v2.c
+++ /dev/null
@@ -1,3108 +0,0 @@
-/* Copyright 2014 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.
- *
- * Battery charging task and state machine.
- */
-
-#include "battery.h"
-#include "battery_smart.h"
-#include "charge_manager.h"
-#include "charger_profile_override.h"
-#include "charge_state.h"
-#include "charger.h"
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "ec_commands.h"
-#include "ec_ec_comm_client.h"
-#include "ec_ec_comm_server.h"
-#include "extpower.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "i2c.h"
-#include "math_util.h"
-#include "power.h"
-#include "printf.h"
-#include "system.h"
-#include "task.h"
-#include "throttle_ap.h"
-#include "timer.h"
-#include "usb_common.h"
-#include "usb_pd.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_CHARGER, outstr)
-#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args)
-
-/* Extra debugging prints when allocating power between lid and base. */
-#undef CHARGE_ALLOCATE_EXTRA_DEBUG
-
-#define CRITICAL_BATTERY_SHUTDOWN_TIMEOUT_US \
- (CONFIG_BATTERY_CRITICAL_SHUTDOWN_TIMEOUT * SECOND)
-#define PRECHARGE_TIMEOUT_US (PRECHARGE_TIMEOUT * SECOND)
-#define LFCC_EVENT_THRESH 5 /* Full-capacity change reqd for host event */
-
-#ifdef CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT
-#ifndef CONFIG_HOSTCMD_EVENTS
-#error "CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT needs CONFIG_HOSTCMD_EVENTS"
-#endif /* CONFIG_HOSTCMD_EVENTS */
-#define BAT_OCP_TIMEOUT_US (60 * SECOND)
-/* BAT_OCP_HYSTERESIS_PCT can be optionally overridden in board.h. */
-#ifndef BAT_OCP_HYSTERESIS_PCT
-#define BAT_OCP_HYSTERESIS_PCT 10
-#endif /* BAT_OCP_HYSTERESIS_PCT */
-#define BAT_OCP_HYSTERESIS \
- (BAT_MAX_DISCHG_CURRENT * BAT_OCP_HYSTERESIS_PCT / 100) /* mA */
-#endif /* CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT */
-
-#ifdef CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE
-#ifndef CONFIG_HOSTCMD_EVENTS
-#error "CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE needs CONFIG_HOSTCMD_EVENTS"
-#endif /* CONFIG_HOSTCMD_EVENTS */
-#define BAT_UVP_TIMEOUT_US (60 * SECOND)
-/* BAT_UVP_HYSTERESIS_PCT can be optionally overridden in board.h. */
-#ifndef BAT_UVP_HYSTERESIS_PCT
-#define BAT_UVP_HYSTERESIS_PCT 3
-#endif /* BAT_UVP_HYSTERESIS_PCT */
-#define BAT_UVP_HYSTERESIS \
- (BAT_LOW_VOLTAGE_THRESH * BAT_UVP_HYSTERESIS_PCT / 100) /* mV */
-static timestamp_t uvp_throttle_start_time;
-#endif /* CONFIG_THROTTLE_AP_ON_BAT_OLTAGE */
-
-static int charge_request(int voltage, int current);
-
-static uint8_t battery_level_shutdown;
-
-/*
- * State for charger_task(). Here so we can reset it on a HOOK_INIT, and
- * because stack space is more limited than .bss
- */
-static const struct battery_info *batt_info;
-static struct charge_state_data curr;
-static enum charge_state_v2 prev_state;
-static int prev_ac, prev_charge, prev_full, prev_disp_charge;
-static enum battery_present prev_bp;
-static int is_full; /* battery not accepting current */
-static enum ec_charge_control_mode chg_ctl_mode;
-static int manual_voltage; /* Manual voltage override (-1 = no override) */
-static int manual_current; /* Manual current override (-1 = no override) */
-static unsigned int user_current_limit = -1U;
-test_export_static timestamp_t shutdown_target_time;
-static timestamp_t precharge_start_time;
-static struct sustain_soc sustain_soc;
-
-/*
- * The timestamp when the battery charging current becomes stable.
- * When a new charging status happens, charger needs several seconds to
- * stabilize the battery charging current.
- * stable_current should be evaluated when stable_ts expired.
- * stable_ts should be reset if the charger input voltage/current changes,
- * or a new battery charging voltage/request happened.
- * By evaluating stable_current, we can evaluate the battery's desired charging
- * power desired_mw. This allow us to have a better charging efficiency by
- * negotiating the most fit PDO, i.e. the PDO provides the power just enough for
- * the system and battery, or the PDO with preferred voltage.
- */
-STATIC_IF(CONFIG_USB_PD_PREFER_MV) timestamp_t stable_ts;
-/* battery charging current evaluated after stable_ts expired */
-STATIC_IF(CONFIG_USB_PD_PREFER_MV) int stable_current;
-/* battery desired power in mW. This is used to negotiate the suitable PDO */
-STATIC_IF(CONFIG_USB_PD_PREFER_MV) int desired_mw;
-STATIC_IF_NOT(CONFIG_USB_PD_PREFER_MV) struct pd_pref_config_t pd_pref_config;
-
-#ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT
-static int base_connected;
-/* Base has responded to one of our commands already. */
-static int base_responsive;
-static int charge_base;
-static int prev_charge_base;
-static int prev_current_base;
-static int prev_allow_charge_base;
-static int prev_current_lid;
-
-/*
- * In debugging mode, with AC, input current to allocate to base. Negative
- * value disables manual mode.
- */
-static int manual_ac_current_base = -1;
-/*
- * In debugging mode, when discharging, current to transfer from lid to base
- * (negative to transfer from base to lid). Only valid when enabled is true.
- */
-static int manual_noac_enabled;
-static int manual_noac_current_base;
-#else
-static const int base_connected;
-#endif
-
-/* Is battery connected but unresponsive after precharge? */
-static int battery_seems_dead;
-
-static int battery_seems_disconnected;
-
-/*
- * Was battery removed? Set when we see BP_NO, cleared after the battery is
- * reattached and becomes responsive. Used to indicate an error state after
- * removal and trigger re-reading the battery static info when battery is
- * reattached and responsive.
- */
-static int battery_was_removed;
-
-static int problems_exist;
-static int debugging;
-
-
-/* Track problems in communicating with the battery or charger */
-enum problem_type {
- PR_STATIC_UPDATE,
- PR_SET_VOLTAGE,
- PR_SET_CURRENT,
- PR_SET_MODE,
- PR_SET_INPUT_CURR,
- PR_POST_INIT,
- PR_CHG_FLAGS,
- PR_BATT_FLAGS,
- PR_CUSTOM,
- PR_CFG_SEC_CHG,
-
- NUM_PROBLEM_TYPES
-};
-static const char * const prob_text[] = {
- "static update",
- "set voltage",
- "set current",
- "set mode",
- "set input current",
- "post init",
- "chg params",
- "batt params",
- "custom profile",
- "cfg secondary chg"
-};
-BUILD_ASSERT(ARRAY_SIZE(prob_text) == NUM_PROBLEM_TYPES);
-
-/*
- * TODO(crosbug.com/p/27639): When do we decide a problem is real and not
- * just intermittent? And what do we do about it?
- */
-static void problem(enum problem_type p, int v)
-{
- static int __bss_slow last_prob_val[NUM_PROBLEM_TYPES];
- static timestamp_t __bss_slow last_prob_time[NUM_PROBLEM_TYPES];
- timestamp_t t_now, t_diff;
-
- if (last_prob_val[p] != v) {
- t_now = get_time();
- t_diff.val = t_now.val - last_prob_time[p].val;
- CPRINTS("charge problem: %s, 0x%x -> 0x%x after %.6" PRId64 "s",
- prob_text[p], last_prob_val[p], v, t_diff.val);
- last_prob_val[p] = v;
- last_prob_time[p] = t_now;
- }
- problems_exist = 1;
-}
-
-test_export_static enum ec_charge_control_mode get_chg_ctrl_mode(void)
-{
- return chg_ctl_mode;
-}
-
-static int battery_sustainer_set(int8_t lower, int8_t upper)
-{
- if (lower == -1 || upper == -1) {
- CPRINTS("Sustain mode disabled");
- sustain_soc.lower = -1;
- sustain_soc.upper = -1;
- return EC_SUCCESS;
- }
-
- if (lower <= upper && 0 <= lower && upper <= 100) {
- /* Currently sustainer requires discharge_on_ac. */
- if (!IS_ENABLED(CONFIG_CHARGER_DISCHARGE_ON_AC))
- return EC_RES_UNAVAILABLE;
- sustain_soc.lower = lower;
- sustain_soc.upper = upper;
- return EC_SUCCESS;
- }
-
- CPRINTS("Invalid param: %s(%d, %d)", __func__, lower, upper);
- return EC_ERROR_INVAL;
-}
-
-static void battery_sustainer_disable(void)
-{
- battery_sustainer_set(-1, -1);
-}
-
-static bool battery_sustainer_enabled(void)
-{
- return sustain_soc.lower != -1 && sustain_soc.upper != -1;
-}
-
-#ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT
-/*
- * Parameters for dual-battery policy.
- * TODO(b:71881017): This should be made configurable by AP in the future.
- */
-struct dual_battery_policy {
- /*** Policies when AC is not connected. ***/
- /* Voltage to use when using OTG mode between lid and base (mV) */
- uint16_t otg_voltage;
- /* Maximum current to apply from base to lid (mA) */
- uint16_t max_base_to_lid_current;
- /*
- * Margin to apply between provided OTG output current and input current
- * limit, to make sure that input charger does not overcurrent output
- * charger. input_current = (1-margin) * output_current. (/128)
- */
- uint8_t margin_otg_current;
-
- /* Only do base to lid OTG when base battery above this value (%) */
- uint8_t min_charge_base_otg;
-
- /*
- * When base/lid battery percentage is below this value, do
- * battery-to-battery charging. (%)
- */
- uint8_t max_charge_base_batt_to_batt;
- uint8_t max_charge_lid_batt_to_batt;
-
- /*** Policies when AC is connected. ***/
- /* Minimum power to allocate to base (mW), includes some margin to allow
- * base to charge when critically low.
- */
- uint16_t min_base_system_power;
-
- /* Smoothing factor for lid power (/128) */
- uint8_t lid_system_power_smooth;
- /*
- * Smoothing factor for base/lid battery power, when the battery power
- * is decreasing only: we try to estimate the maximum power that the
- * battery is willing to take and always reset it when it draws more
- * than the estimate. (/128)
- */
- uint8_t battery_power_smooth;
-
- /*
- * Margin to add to requested base/lid battery power, to figure out how
- * much current to allocate. allocation = (1+margin) * request. (/128)
- */
- uint8_t margin_base_battery_power;
- uint8_t margin_lid_battery_power;
-
- /* Maximum current to apply from lid to base (mA) */
- uint16_t max_lid_to_base_current;
-};
-
-static const struct dual_battery_policy db_policy = {
- .otg_voltage = 12000, /* mV */
- .max_base_to_lid_current = 1800, /* mA, about 2000mA with margin. */
- .margin_otg_current = 13, /* /128 = 10.1% */
- .min_charge_base_otg = 5, /* % */
- .max_charge_base_batt_to_batt = 4, /* % */
- .max_charge_lid_batt_to_batt = 10, /* % */
- .min_base_system_power = 1300, /* mW */
- .lid_system_power_smooth = 32, /* 32/128 = 0.25 */
- .battery_power_smooth = 1, /* 1/128 = 0.008 */
- .margin_base_battery_power = 32, /* 32/128 = 0.25 */
- .margin_lid_battery_power = 32, /* 32/128 = 0.25 */
- .max_lid_to_base_current = 2000, /* mA */
-};
-
-/* Add at most "value" to power_var, subtracting from total_power budget. */
-#define CHG_ALLOCATE(power_var, total_power, value) do { \
- int val_capped = MIN(value, total_power); \
- (power_var) += val_capped; \
- (total_power) -= val_capped; \
-} while (0)
-
-/* Update base battery information */
-static void update_base_battery_info(void)
-{
- struct ec_response_battery_dynamic_info *const bd =
- &battery_dynamic[BATT_IDX_BASE];
-
- base_connected = board_is_base_connected();
-
- if (!base_connected) {
- const int invalid_flags = EC_BATT_FLAG_INVALID_DATA;
- /* Invalidate static/dynamic information */
- if (bd->flags != invalid_flags) {
- bd->flags = invalid_flags;
-
- host_set_single_event(EC_HOST_EVENT_BATTERY);
- host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS);
- }
- charge_base = -1;
- base_responsive = 0;
- prev_current_base = 0;
- prev_allow_charge_base = 0;
- } else if (base_responsive) {
- int old_flags = bd->flags;
- int flags_changed;
- int old_full_capacity = bd->full_capacity;
-
- ec_ec_client_base_get_dynamic_info();
- flags_changed = (old_flags != bd->flags);
- /* Fetch static information when flags change. */
- if (flags_changed)
- ec_ec_client_base_get_static_info();
-
- battery_memmap_refresh(BATT_IDX_BASE);
-
- /* Newly connected battery, or change in capacity. */
- if (old_flags & EC_BATT_FLAG_INVALID_DATA ||
- ((old_flags & EC_BATT_FLAG_BATT_PRESENT) !=
- (bd->flags & EC_BATT_FLAG_BATT_PRESENT)) ||
- old_full_capacity != bd->full_capacity)
- host_set_single_event(EC_HOST_EVENT_BATTERY);
-
- if (flags_changed)
- host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS);
-
- /* Update charge_base */
- if (bd->flags & (BATT_FLAG_BAD_FULL_CAPACITY |
- BATT_FLAG_BAD_REMAINING_CAPACITY))
- charge_base = -1;
- else if (bd->full_capacity > 0)
- charge_base = 100 * bd->remaining_capacity
- / bd->full_capacity;
- else
- charge_base = 0;
- }
-}
-
-/**
- * Setup current settings for base, and record previous values, if the base
- * is responsive.
- *
- * @param current_base Current to be drawn by base (negative to provide power)
- * @param allow_charge_base Whether base battery should be charged (only makes
- * sense with positive current)
- */
-static int set_base_current(int current_base, int allow_charge_base)
-{
- /* "OTG" voltage from base to lid. */
- const int otg_voltage = db_policy.otg_voltage;
- int ret;
-
- ret = ec_ec_client_base_charge_control(current_base,
- otg_voltage, allow_charge_base);
- if (ret) {
- /* Ignore errors until the base is responsive. */
- if (base_responsive)
- return ret;
- } else {
- base_responsive = 1;
- prev_current_base = current_base;
- prev_allow_charge_base = allow_charge_base;
- }
-
- return EC_RES_SUCCESS;
-}
-
-/**
- * Setup current settings for lid and base, in a safe way.
- *
- * @param current_base Current to be drawn by base (negative to provide power)
- * @param allow_charge_base Whether base battery should be charged (only makes
- * sense with positive current)
- * @param current_lid Current to be drawn by lid (negative to provide power)
- * @param allow_charge_lid Whether lid battery should be charged
- */
-static void set_base_lid_current(int current_base, int allow_charge_base,
- int current_lid, int allow_charge_lid)
-{
- /* "OTG" voltage from lid to base. */
- const int otg_voltage = db_policy.otg_voltage;
-
- int lid_first;
- int ret;
- int chgnum = 0;
-
- /* TODO(b:71881017): This is still quite verbose during charging. */
- if (prev_current_base != current_base ||
- prev_allow_charge_base != allow_charge_base ||
- prev_current_lid != current_lid) {
- CPRINTS("Base/Lid: %d%s/%d%s mA",
- current_base, allow_charge_base ? "+" : "",
- current_lid, allow_charge_lid ? "+" : "");
- }
-
- /*
- * To decide whether to first control the lid or the base, we first
- * control the side that _reduces_ current that would be drawn, then
- * setup one that would start providing power, then increase current.
- */
- if (current_lid >= 0 && current_lid < prev_current_lid)
- lid_first = 1; /* Lid decreases current */
- else if (current_base >= 0 && current_base < prev_current_base)
- lid_first = 0; /* Base decreases current */
- else if (current_lid < 0)
- lid_first = 1; /* Lid provide power */
- else
- lid_first = 0; /* All other cases: control the base first */
-
- if (!lid_first && base_connected) {
- ret = set_base_current(current_base, allow_charge_base);
- if (ret)
- return;
- }
-
- if (current_lid >= 0) {
- ret = charge_set_output_current_limit(CHARGER_SOLO, 0, 0);
- if (ret)
- return;
- ret = charger_set_input_current_limit(chgnum, current_lid);
- if (ret)
- return;
- if (allow_charge_lid)
- ret = charge_request(curr.requested_voltage,
- curr.requested_current);
- else
- ret = charge_request(0, 0);
- } else {
- ret = charge_set_output_current_limit(CHARGER_SOLO,
- -current_lid, otg_voltage);
- }
-
- if (ret)
- return;
-
- prev_current_lid = current_lid;
-
- if (lid_first && base_connected) {
- ret = set_base_current(current_base, allow_charge_base);
- if (ret)
- return;
- }
-
- /*
- * Make sure cross-power is enabled (it might not be enabled right after
- * plugging the base, or when an adapter just got connected).
- */
- if (base_connected && current_base != 0)
- board_enable_base_power(1);
-}
-
-/**
- * Smooth power value, covering some edge cases.
- * Compute s*curr+(1-s)*prev, where s is in 1/128 unit.
- */
-static int smooth_value(int prev, int curr, int s)
-{
- if (curr < 0)
- curr = 0;
- if (prev < 0)
- return curr;
-
- return prev + s * (curr - prev) / 128;
-}
-
-/**
- * Add margin m to value. Compute (1+m)*value, where m is in 1/128 unit.
- */
-static int add_margin(int value, int m)
-{
- return value + m * value / 128;
-}
-
-static void charge_allocate_input_current_limit(void)
-{
- /*
- * All the power numbers are in mW.
- *
- * Since we work with current and voltage in mA and mV, multiplying them
- * gives numbers in uW, which are dangerously close to overflowing when
- * doing intermediate computations (60W * 100 overflows a 32-bit int,
- * for example). We therefore divide the product by 1000 and re-multiply
- * the power numbers by 1000 when converting them back to current.
- */
- int total_power = 0;
-
- static int prev_base_battery_power = -1;
- int base_battery_power = 0;
- int base_battery_power_max = 0;
-
- static int prev_lid_system_power = -1;
- int lid_system_power;
-
- static int prev_lid_battery_power = -1;
- int lid_battery_power = 0;
- int lid_battery_power_max = 0;
-
- int power_base = 0;
- int power_lid = 0;
-
- int current_base = 0;
- int current_lid = 0;
-
- int charge_lid = charge_get_percent();
-
- const struct ec_response_battery_dynamic_info *const base_bd =
- &battery_dynamic[BATT_IDX_BASE];
-
-
- if (!base_connected) {
- set_base_lid_current(0, 0, curr.desired_input_current, 1);
- prev_base_battery_power = -1;
- return;
- }
-
- /* Charging */
- if (curr.desired_input_current > 0 && curr.input_voltage > 0)
- total_power =
- curr.desired_input_current * curr.input_voltage / 1000;
-
- /*
- * TODO(b:71723024): We should be able to replace this test by curr.ac,
- * but the value is currently wrong, especially during transitions.
- */
- if (total_power <= 0) {
- int base_critical = charge_base >= 0 &&
- charge_base < db_policy.max_charge_base_batt_to_batt;
-
- /* Discharging */
- prev_base_battery_power = -1;
- prev_lid_system_power = -1;
- prev_lid_battery_power = -1;
-
- /* Manual control */
- if (manual_noac_enabled) {
- int lid_current, base_current;
-
- if (manual_noac_current_base > 0) {
- base_current = -manual_noac_current_base;
- lid_current =
- add_margin(manual_noac_current_base,
- db_policy.margin_otg_current);
- } else {
- lid_current = manual_noac_current_base;
- base_current =
- add_margin(-manual_noac_current_base,
- db_policy.margin_otg_current);
- }
-
- set_base_lid_current(base_current, 0, lid_current, 0);
- return;
- }
-
- /*
- * System is off, cut power to the base. We'll reset the base
- * when system restarts, or when AC is plugged.
- */
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) {
- set_base_lid_current(0, 0, 0, 0);
- if (base_responsive) {
- /* Base still responsive, put it to sleep. */
- CPRINTF("Hibernating base\n");
- ec_ec_client_hibernate();
- base_responsive = 0;
- board_enable_base_power(0);
- }
- return;
- }
-
- /*
- * System is suspended, let the lid and base run on their
- * own power. However, if the base battery is critically low, we
- * still want to provide power to the base, to make sure it
- * stays alive to be able to wake the system on keyboard or
- * touchpad events.
- */
- if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) &&
- !base_critical) {
- set_base_lid_current(0, 0, 0, 0);
- return;
- }
-
- if (charge_base > db_policy.min_charge_base_otg) {
- int lid_current = db_policy.max_base_to_lid_current;
- int base_current = add_margin(lid_current,
- db_policy.margin_otg_current);
- /* Draw current from base to lid */
- set_base_lid_current(-base_current, 0, lid_current,
- charge_lid < db_policy.max_charge_lid_batt_to_batt);
- } else {
- /*
- * Base battery is too low, apply power to it, and allow
- * it to charge if it is critically low.
- *
- * TODO(b:71881017): When suspended, this will make the
- * battery charge oscillate between 3 and 4 percent,
- * which might not be great for battery life. We need
- * some hysteresis.
- */
- /*
- * TODO(b:71881017): Precompute (ideally, at build time)
- * the base_current, so we do not need to do a division
- * here.
- */
- int base_current =
- (db_policy.min_base_system_power * 1000) /
- db_policy.otg_voltage;
- int lid_current = add_margin(base_current,
- db_policy.margin_otg_current);
-
- set_base_lid_current(base_current, base_critical,
- -lid_current, 0);
- }
-
- return;
- }
-
- /* Manual control */
- if (manual_ac_current_base >= 0) {
- int current_base = manual_ac_current_base;
- int current_lid =
- curr.desired_input_current - manual_ac_current_base;
-
- if (current_lid < 0) {
- current_base = curr.desired_input_current;
- current_lid = 0;
- }
-
- set_base_lid_current(current_base, 1, current_lid, 1);
- return;
- }
-
- /* Estimate system power. */
- lid_system_power = charger_get_system_power() / 1000;
-
- /* Smooth system power, as it is very spiky */
- lid_system_power = smooth_value(prev_lid_system_power,
- lid_system_power, db_policy.lid_system_power_smooth);
- prev_lid_system_power = lid_system_power;
-
- /*
- * TODO(b:71881017): Smoothing the battery power isn't necessarily a
- * good idea: if the system takes up too much power, we may reduce the
- * estimate power too quickly, leading to oscillations when the system
- * power goes down. Instead, we should probably estimate the current
- * based on remaining capacity.
- */
- /* Estimate lid battery power. */
- if (!(curr.batt.flags &
- (BATT_FLAG_BAD_VOLTAGE | BATT_FLAG_BAD_CURRENT)))
- lid_battery_power = curr.batt.current *
- curr.batt.voltage / 1000;
- if (lid_battery_power < prev_lid_battery_power)
- lid_battery_power = smooth_value(prev_lid_battery_power,
- lid_battery_power, db_policy.battery_power_smooth);
- if (!(curr.batt.flags &
- (BATT_FLAG_BAD_DESIRED_VOLTAGE |
- BATT_FLAG_BAD_DESIRED_CURRENT)))
- lid_battery_power_max = curr.batt.desired_current *
- curr.batt.desired_voltage / 1000;
-
- lid_battery_power = MIN(lid_battery_power, lid_battery_power_max);
-
- /* Estimate base battery power. */
- if (!(base_bd->flags & EC_BATT_FLAG_INVALID_DATA)) {
- base_battery_power = base_bd->actual_current *
- base_bd->actual_voltage / 1000;
- base_battery_power_max = base_bd->desired_current *
- base_bd->desired_voltage / 1000;
- }
- if (base_battery_power < prev_base_battery_power)
- base_battery_power = smooth_value(prev_base_battery_power,
- base_battery_power, db_policy.battery_power_smooth);
- base_battery_power = MIN(base_battery_power, base_battery_power_max);
-
- if (debugging) {
- CPRINTF("%s:\n", __func__);
- CPRINTF("total power: %d\n", total_power);
- CPRINTF("base battery power: %d (%d)\n",
- base_battery_power, base_battery_power_max);
- CPRINTF("lid system power: %d\n", lid_system_power);
- CPRINTF("lid battery power: %d\n", lid_battery_power);
- CPRINTF("percent base/lid: %d%% %d%%\n",
- charge_base, charge_lid);
- }
-
- prev_lid_battery_power = lid_battery_power;
- prev_base_battery_power = base_battery_power;
-
- if (total_power > 0) { /* Charging */
- /* Allocate system power */
- CHG_ALLOCATE(power_base, total_power,
- db_policy.min_base_system_power);
- CHG_ALLOCATE(power_lid, total_power, lid_system_power);
-
- /* Allocate lid, then base battery power */
- lid_battery_power = add_margin(lid_battery_power,
- db_policy.margin_lid_battery_power);
- CHG_ALLOCATE(power_lid, total_power, lid_battery_power);
-
- base_battery_power = add_margin(base_battery_power,
- db_policy.margin_base_battery_power);
- CHG_ALLOCATE(power_base, total_power, base_battery_power);
-
- /* Give everything else to the lid. */
- CHG_ALLOCATE(power_lid, total_power, total_power);
- if (debugging)
- CPRINTF("power: base %d mW / lid %d mW\n",
- power_base, power_lid);
-
- current_base = 1000 * power_base / curr.input_voltage;
- current_lid = 1000 * power_lid / curr.input_voltage;
-
- if (current_base > db_policy.max_lid_to_base_current) {
- current_lid += (current_base
- - db_policy.max_lid_to_base_current);
- current_base = db_policy.max_lid_to_base_current;
- }
-
- if (debugging)
- CPRINTF("current: base %d mA / lid %d mA\n",
- current_base, current_lid);
-
- set_base_lid_current(current_base, 1, current_lid, 1);
- } else { /* Discharging */
- }
-
- if (debugging)
- CPRINTF("====\n");
-}
-#endif /* CONFIG_EC_EC_COMM_BATTERY_CLIENT */
-
-#ifndef CONFIG_BATTERY_V2
-/* Returns zero if every item was updated. */
-static int update_static_battery_info(void)
-{
- char *batt_str;
- int batt_serial;
- uint8_t batt_flags = 0;
- /*
- * The return values have type enum ec_error_list, but EC_SUCCESS is
- * zero. We'll just look for any failures so we can try them all again.
- */
- int rv;
-
- /* Smart battery serial number is 16 bits */
- batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_SERIAL);
- memset(batt_str, 0, EC_MEMMAP_TEXT_MAX);
- rv = battery_serial_number(&batt_serial);
- if (!rv)
- snprintf(batt_str, EC_MEMMAP_TEXT_MAX, "%04X", batt_serial);
-
- /* Design Capacity of Full */
- rv |= battery_design_capacity(
- (int *)host_get_memmap(EC_MEMMAP_BATT_DCAP));
-
- /* Design Voltage */
- rv |= battery_design_voltage(
- (int *)host_get_memmap(EC_MEMMAP_BATT_DVLT));
-
- /* Last Full Charge Capacity (this is only mostly static) */
- rv |= battery_full_charge_capacity(
- (int *)host_get_memmap(EC_MEMMAP_BATT_LFCC));
-
- /* Cycle Count */
- rv |= battery_cycle_count((int *)host_get_memmap(EC_MEMMAP_BATT_CCNT));
-
- /* Battery Manufacturer string */
- batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MFGR);
- memset(batt_str, 0, EC_MEMMAP_TEXT_MAX);
- rv |= battery_manufacturer_name(batt_str, EC_MEMMAP_TEXT_MAX);
-
- /* Battery Model string */
- batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MODEL);
- memset(batt_str, 0, EC_MEMMAP_TEXT_MAX);
- rv |= battery_device_name(batt_str, EC_MEMMAP_TEXT_MAX);
-
- /* Battery Type string */
- batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_TYPE);
- rv |= battery_device_chemistry(batt_str, EC_MEMMAP_TEXT_MAX);
-
- /* Zero the dynamic entries. They'll come next. */
- *(int *)host_get_memmap(EC_MEMMAP_BATT_VOLT) = 0;
- *(int *)host_get_memmap(EC_MEMMAP_BATT_RATE) = 0;
- *(int *)host_get_memmap(EC_MEMMAP_BATT_CAP) = 0;
- *(int *)host_get_memmap(EC_MEMMAP_BATT_LFCC) = 0;
- if (extpower_is_present())
- batt_flags |= EC_BATT_FLAG_AC_PRESENT;
- *host_get_memmap(EC_MEMMAP_BATT_FLAG) = batt_flags;
-
- if (rv)
- problem(PR_STATIC_UPDATE, rv);
- else
- /* No errors seen. Battery data is now present */
- *host_get_memmap(EC_MEMMAP_BATTERY_VERSION) = 1;
-
- return rv;
-}
-
-static void update_dynamic_battery_info(void)
-{
- /* The memmap address is constant. We should fix these calls somehow. */
- int *memmap_volt = (int *)host_get_memmap(EC_MEMMAP_BATT_VOLT);
- int *memmap_rate = (int *)host_get_memmap(EC_MEMMAP_BATT_RATE);
- int *memmap_cap = (int *)host_get_memmap(EC_MEMMAP_BATT_CAP);
- int *memmap_lfcc = (int *)host_get_memmap(EC_MEMMAP_BATT_LFCC);
- uint8_t *memmap_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG);
- uint8_t tmp;
- int send_batt_status_event = 0;
- int send_batt_info_event = 0;
- static int __bss_slow batt_present;
-
- tmp = 0;
- if (curr.ac)
- tmp |= EC_BATT_FLAG_AC_PRESENT;
-
- if (curr.batt.is_present == BP_YES) {
- tmp |= EC_BATT_FLAG_BATT_PRESENT;
- batt_present = 1;
- /* Tell the AP to read battery info if it is newly present. */
- if (!(*memmap_flags & EC_BATT_FLAG_BATT_PRESENT))
- send_batt_info_event++;
- } else {
- /*
- * Require two consecutive updates with BP_NOT_SURE
- * before reporting it gone to the host.
- */
- if (batt_present)
- tmp |= EC_BATT_FLAG_BATT_PRESENT;
- else if (*memmap_flags & EC_BATT_FLAG_BATT_PRESENT)
- send_batt_info_event++;
- batt_present = 0;
- }
-
- if (curr.batt.flags & EC_BATT_FLAG_INVALID_DATA)
- tmp |= EC_BATT_FLAG_INVALID_DATA;
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_VOLTAGE))
- *memmap_volt = curr.batt.voltage;
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_CURRENT))
- *memmap_rate = ABS(curr.batt.current);
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_REMAINING_CAPACITY)) {
- /*
- * If we're running off the battery, it must have some charge.
- * Don't report zero charge, as that has special meaning
- * to Chrome OS powerd.
- */
- if (curr.batt.remaining_capacity == 0 && !curr.batt_is_charging)
- *memmap_cap = 1;
- else
- *memmap_cap = curr.batt.remaining_capacity;
- }
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_FULL_CAPACITY) &&
- (curr.batt.full_capacity <= (*memmap_lfcc - LFCC_EVENT_THRESH) ||
- curr.batt.full_capacity >= (*memmap_lfcc + LFCC_EVENT_THRESH))) {
- *memmap_lfcc = curr.batt.full_capacity;
- /* Poke the AP if the full_capacity changes. */
- send_batt_info_event++;
- }
-
- if (curr.batt.is_present == BP_YES &&
- !(curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) &&
- curr.batt.state_of_charge <= BATTERY_LEVEL_CRITICAL)
- tmp |= EC_BATT_FLAG_LEVEL_CRITICAL;
-
- tmp |= curr.batt_is_charging ? EC_BATT_FLAG_CHARGING :
- EC_BATT_FLAG_DISCHARGING;
-
- /* Tell the AP to re-read battery status if charge state changes */
- if (*memmap_flags != tmp)
- send_batt_status_event++;
-
- /* Update flags before sending host events. */
- *memmap_flags = tmp;
-
- if (send_batt_info_event)
- host_set_single_event(EC_HOST_EVENT_BATTERY);
- if (send_batt_status_event)
- host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS);
-}
-#else /* CONFIG_BATTERY_V2 */
-
-static int is_battery_string_reliable(const char *buf)
-{
- /*
- * From is_string_printable rule, 0xFF is not printable.
- * So, EC should think battery string is unreliable if string
- * include 0xFF.
- */
- while (*buf) {
- if ((*buf) == 0xFF)
- return 0;
- buf++;
- }
-
- return 1;
-}
-
-static int update_static_battery_info(void)
-{
- int batt_serial;
- int val;
- /*
- * The return values have type enum ec_error_list, but EC_SUCCESS is
- * zero. We'll just look for any failures so we can try them all again.
- */
- int rv, ret;
-
- struct ec_response_battery_static_info_v1 *const bs =
- &battery_static[BATT_IDX_MAIN];
-
- /* Clear all static information. */
- memset(bs, 0, sizeof(*bs));
-
- /* Smart battery serial number is 16 bits */
- rv = battery_serial_number(&batt_serial);
- if (!rv)
- snprintf(bs->serial_ext, sizeof(bs->serial_ext),
- "%04X", batt_serial);
-
- /* Design Capacity of Full */
- ret = battery_design_capacity(&val);
- if (!ret)
- bs->design_capacity = val;
- rv |= ret;
-
- /* Design Voltage */
- ret = battery_design_voltage(&val);
- if (!ret)
- bs->design_voltage = val;
- rv |= ret;
-
- /* Cycle Count */
- ret = battery_cycle_count(&val);
- if (!ret)
- bs->cycle_count = val;
- rv |= ret;
-
- /* Battery Manufacturer string */
- rv |= battery_manufacturer_name(bs->manufacturer_ext,
- sizeof(bs->manufacturer_ext));
-
- /* Battery Model string */
- rv |= battery_device_name(bs->model_ext, sizeof(bs->model_ext));
-
- /* Battery Type string */
- rv |= battery_device_chemistry(bs->type_ext, sizeof(bs->type_ext));
-
- /*
- * b/181639264: Battery gauge follow SMBus SPEC and SMBus define
- * cumulative clock low extend time for both controller (master) and
- * peripheral (slave). However, I2C doesn't.
- * Regarding this issue, we observe EC sometimes pull I2C CLK low
- * a while after EC start running. Actually, we are not sure the
- * reason until now.
- * If EC pull I2C CLK low too long, and it may cause battery fw timeout
- * because battery count cumulative clock extend time over 25ms.
- * When it happened, battery will release both its CLK and DATA and
- * reset itself. So, EC may get 0xFF when EC keep reading data from
- * battery. Battery static information will be unreliable and need to
- * be updated.
- * This change is improvement that EC should retry if battery string is
- * unreliable.
- */
- if (!is_battery_string_reliable(bs->serial_ext) ||
- !is_battery_string_reliable(bs->manufacturer_ext) ||
- !is_battery_string_reliable(bs->model_ext) ||
- !is_battery_string_reliable(bs->type_ext))
- rv |= EC_ERROR_UNKNOWN;
-
- /* Zero the dynamic entries. They'll come next. */
- memset(&battery_dynamic[BATT_IDX_MAIN], 0,
- sizeof(battery_dynamic[BATT_IDX_MAIN]));
-
- if (rv)
- problem(PR_STATIC_UPDATE, rv);
-
-#ifdef HAS_TASK_HOSTCMD
- battery_memmap_refresh(BATT_IDX_MAIN);
-#endif
-
- return rv;
-}
-
-static void update_dynamic_battery_info(void)
-{
- static int __bss_slow batt_present;
- uint8_t tmp;
- int send_batt_status_event = 0;
- int send_batt_info_event = 0;
-
- struct ec_response_battery_dynamic_info *const bd =
- &battery_dynamic[BATT_IDX_MAIN];
-
- tmp = 0;
- if (curr.ac)
- tmp |= EC_BATT_FLAG_AC_PRESENT;
-
- if (curr.batt.is_present == BP_YES) {
- tmp |= EC_BATT_FLAG_BATT_PRESENT;
- batt_present = 1;
- /* Tell the AP to read battery info if it is newly present. */
- if (!(bd->flags & EC_BATT_FLAG_BATT_PRESENT))
- send_batt_info_event++;
- } else {
- /*
- * Require two consecutive updates with BP_NOT_SURE
- * before reporting it gone to the host.
- */
- if (batt_present)
- tmp |= EC_BATT_FLAG_BATT_PRESENT;
- else if (bd->flags & EC_BATT_FLAG_BATT_PRESENT)
- send_batt_info_event++;
- batt_present = 0;
- }
-
- if (curr.batt.flags & EC_BATT_FLAG_INVALID_DATA)
- tmp |= EC_BATT_FLAG_INVALID_DATA;
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_VOLTAGE))
- bd->actual_voltage = curr.batt.voltage;
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_CURRENT))
- bd->actual_current = curr.batt.current;
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_DESIRED_VOLTAGE))
- bd->desired_voltage = curr.batt.desired_voltage;
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_DESIRED_CURRENT))
- bd->desired_current = curr.batt.desired_current;
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_REMAINING_CAPACITY)) {
- /*
- * If we're running off the battery, it must have some charge.
- * Don't report zero charge, as that has special meaning
- * to Chrome OS powerd.
- */
- if (curr.batt.remaining_capacity == 0 && !curr.batt_is_charging)
- bd->remaining_capacity = 1;
- else
- bd->remaining_capacity = curr.batt.remaining_capacity;
- }
-
- if (!(curr.batt.flags & BATT_FLAG_BAD_FULL_CAPACITY) &&
- (curr.batt.full_capacity <=
- (bd->full_capacity - LFCC_EVENT_THRESH) ||
- curr.batt.full_capacity >=
- (bd->full_capacity + LFCC_EVENT_THRESH))) {
- bd->full_capacity = curr.batt.full_capacity;
- /* Poke the AP if the full_capacity changes. */
- send_batt_info_event++;
- }
-
- if (curr.batt.is_present == BP_YES &&
- !(curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) &&
- curr.batt.state_of_charge <= BATTERY_LEVEL_CRITICAL)
- tmp |= EC_BATT_FLAG_LEVEL_CRITICAL;
-
- tmp |= curr.batt_is_charging ? EC_BATT_FLAG_CHARGING :
- EC_BATT_FLAG_DISCHARGING;
-
- /* Tell the AP to re-read battery status if charge state changes */
- if (bd->flags != tmp)
- send_batt_status_event++;
-
- bd->flags = tmp;
-
-#ifdef HAS_TASK_HOSTCMD
- battery_memmap_refresh(BATT_IDX_MAIN);
-#endif
-
-#ifdef CONFIG_HOSTCMD_EVENTS
- if (send_batt_info_event)
- host_set_single_event(EC_HOST_EVENT_BATTERY);
- if (send_batt_status_event)
- host_set_single_event(EC_HOST_EVENT_BATTERY_STATUS);
-#endif
-}
-#endif /* CONFIG_BATTERY_V2 */
-
-static const char * const state_list[] = {
- "idle", "discharge", "charge", "precharge"
-};
-BUILD_ASSERT(ARRAY_SIZE(state_list) == NUM_STATES_V2);
-static const char * const batt_pres[] = {
- "NO", "YES", "NOT_SURE",
-};
-
-const char *mode_text[] = EC_CHARGE_MODE_TEXT;
-BUILD_ASSERT(ARRAY_SIZE(mode_text) == CHARGE_CONTROL_COUNT);
-
-static void dump_charge_state(void)
-{
-#define DUMP(FLD, FMT) ccprintf(#FLD " = " FMT "\n", curr.FLD)
-#define DUMP_CHG(FLD, FMT) ccprintf("\t" #FLD " = " FMT "\n", curr.chg. FLD)
-#define DUMP_BATT(FLD, FMT) ccprintf("\t" #FLD " = " FMT "\n", curr.batt. FLD)
-#define DUMP_OCPC(FLD, FMT) ccprintf("\t" #FLD " = " FMT "\n", curr.ocpc. FLD)
-
- enum ec_charge_control_mode cmode = get_chg_ctrl_mode();
-
- ccprintf("state = %s\n", state_list[curr.state]);
- DUMP(ac, "%d");
- DUMP(batt_is_charging, "%d");
- ccprintf("chg.*:\n");
- DUMP_CHG(voltage, "%dmV");
- DUMP_CHG(current, "%dmA");
- DUMP_CHG(input_current, "%dmA");
- DUMP_CHG(status, "0x%x");
- DUMP_CHG(option, "0x%x");
- DUMP_CHG(flags, "0x%x");
- cflush();
- ccprintf("batt.*:\n");
- ccprintf("\ttemperature = %dC\n",
- DECI_KELVIN_TO_CELSIUS(curr.batt.temperature));
- DUMP_BATT(state_of_charge, "%d%%");
- DUMP_BATT(voltage, "%dmV");
- DUMP_BATT(current, "%dmA");
- DUMP_BATT(desired_voltage, "%dmV");
- DUMP_BATT(desired_current, "%dmA");
- DUMP_BATT(flags, "0x%x");
- DUMP_BATT(remaining_capacity, "%dmAh");
- DUMP_BATT(full_capacity, "%dmAh");
- ccprintf("\tis_present = %s\n", batt_pres[curr.batt.is_present]);
- cflush();
-#ifdef CONFIG_OCPC
- ccprintf("ocpc.*:\n");
- DUMP_OCPC(active_chg_chip, "%d");
- DUMP_OCPC(combined_rsys_rbatt_mo, "%dmOhm");
- if ((curr.ocpc.active_chg_chip != -1) &&
- !(curr.ocpc.chg_flags[curr.ocpc.active_chg_chip] &
- OCPC_NO_ISYS_MEAS_CAP)) {
- DUMP_OCPC(rbatt_mo, "%dmOhm");
- DUMP_OCPC(rsys_mo, "%dmOhm");
- DUMP_OCPC(isys_ma, "%dmA");
- }
- DUMP_OCPC(vsys_aux_mv, "%dmV");
- DUMP_OCPC(vsys_mv, "%dmV");
- DUMP_OCPC(primary_vbus_mv, "%dmV");
- DUMP_OCPC(primary_ibus_ma, "%dmA");
- DUMP_OCPC(secondary_vbus_mv, "%dmV");
- DUMP_OCPC(secondary_ibus_ma, "%dmA");
- DUMP_OCPC(last_error, "%d");
- DUMP_OCPC(integral, "%d");
- DUMP_OCPC(last_vsys, "%dmV");
- cflush();
-#endif /* CONFIG_OCPC */
- DUMP(requested_voltage, "%dmV");
- DUMP(requested_current, "%dmA");
-#ifdef CONFIG_CHARGER_OTG
- DUMP(output_current, "%dmA");
-#endif
-#ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT
- DUMP(input_voltage, "%dmV");
-#endif
- ccprintf("chg_ctl_mode = %s (%d)\n",
- cmode < CHARGE_CONTROL_COUNT ? mode_text[cmode] : "UNDEF",
- cmode);
- ccprintf("manual_voltage = %d\n", manual_voltage);
- ccprintf("manual_current = %d\n", manual_current);
- ccprintf("user_current_limit = %dmA\n", user_current_limit);
- ccprintf("battery_seems_dead = %d\n", battery_seems_dead);
- ccprintf("battery_seems_disconnected = %d\n",
- battery_seems_disconnected);
- ccprintf("battery_was_removed = %d\n", battery_was_removed);
- ccprintf("debug output = %s\n", debugging ? "on" : "off");
- ccprintf("Battery sustainer = %s (%d%% ~ %d%%)\n",
- battery_sustainer_enabled() ? "on" : "off",
- sustain_soc.lower, sustain_soc.upper);
-#undef DUMP
-}
-
-static void show_charging_progress(void)
-{
- int rv = 0, minutes, to_full, chgnum = 0;
- int dsoc;
-
-#ifdef CONFIG_BATTERY_SMART
- /*
- * Predicted remaining battery capacity based on AverageCurrent().
- * 65535 = Battery is not being discharged.
- */
- if (!battery_time_to_empty(&minutes) && minutes != 65535)
- to_full = 0;
- /*
- * Predicted time-to-full charge based on AverageCurrent().
- * 65535 = Battery is not being discharged.
- */
- else if (!battery_time_to_full(&minutes) && minutes != 65535)
- to_full = 1;
- /*
- * If both time to empty and time to full have invalid data, consider
- * measured current from the coulomb counter and ac present status to
- * decide whether battery is about to full or empty.
- */
- else {
- to_full = curr.batt_is_charging;
- rv = EC_ERROR_UNKNOWN;
- }
-#else
- if (!curr.batt_is_charging) {
- rv = battery_time_to_empty(&minutes);
- to_full = 0;
- } else {
- rv = battery_time_to_full(&minutes);
- to_full = 1;
- }
-#endif
-
- dsoc = charge_get_display_charge();
- if (rv)
- CPRINTS("Battery %d%% (Display %d.%d %%) / ??h:?? %s%s",
- curr.batt.state_of_charge,
- dsoc / 10, dsoc % 10,
- to_full ? "to full" : "to empty",
- is_full ? ", not accepting current" : "");
- else
- CPRINTS("Battery %d%% (Display %d.%d %%) / %dh:%d %s%s",
- curr.batt.state_of_charge,
- dsoc / 10, dsoc % 10, minutes / 60, minutes % 60,
- to_full ? "to full" : "to empty",
- is_full ? ", not accepting current" : "");
-
-#ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT
- CPRINTS("Base battery %d%%", charge_base);
-#endif
-
- if (debugging) {
- ccprintf("battery:\n");
- print_battery_debug();
- ccprintf("charger:\n");
- if (IS_ENABLED(CONFIG_OCPC))
- chgnum = charge_get_active_chg_chip();
- print_charger_debug(chgnum);
- ccprintf("chg:\n");
- dump_charge_state();
- }
-}
-
-/* Calculate if battery is full based on whether it is accepting charge */
-test_mockable int calc_is_full(void)
-{
- static int __bss_slow ret;
-
- /* If bad state of charge reading, return last value */
- if (curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE ||
- curr.batt.state_of_charge > 100)
- return ret;
- /*
- * Battery is full when SoC is above 90% and battery desired current
- * is 0. This is necessary because some batteries stop charging when
- * the SoC still reports <100%, so we need to check desired current
- * to know if it is actually full.
- */
- ret = (curr.batt.state_of_charge >= 90 &&
- curr.batt.desired_current == 0);
- return ret;
-}
-
-/*
- * Ask the charger for some voltage and current. If either value is 0,
- * charging is disabled; otherwise it's enabled. Negative values are ignored.
- */
-static int charge_request(int voltage, int current)
-{
- int r1 = EC_SUCCESS, r2 = EC_SUCCESS, r3 = EC_SUCCESS, r4 = EC_SUCCESS;
- static int __bss_slow prev_volt, prev_curr;
-
- if (!voltage || !current) {
-#ifdef CONFIG_CHARGER_NARROW_VDC
- current = 0;
- /*
- * With NVDC charger, keep VSYS voltage higher than battery,
- * otherwise the BGATE FET body diode would conduct and
- * discharge the battery.
- */
- voltage = charger_closest_voltage(
- curr.batt.voltage + charger_get_info()->voltage_step);
- /* If the battery is full, request the max voltage. */
- if (is_full)
- voltage = battery_get_info()->voltage_max;
- /* And handle dead battery case */
- voltage = MAX(voltage, battery_get_info()->voltage_normal);
-#else
- voltage = current = 0;
-#endif
- }
-
- if (curr.ac) {
- if (prev_volt != voltage || prev_curr != current)
- CPRINTS("%s(%dmV, %dmA)", __func__, voltage, current);
- }
-
- /*
- * Set current before voltage so that if we are just starting
- * to charge, we allow some time (i2c delay) for charging circuit to
- * start at a voltage just above battery voltage before jumping
- * up. This helps avoid large current spikes when connecting
- * battery.
- */
- if (current >= 0) {
-#ifdef CONFIG_OCPC
- /*
- * For OCPC systems, don't unconditionally modify the primary
- * charger IC's charge current. It may be handled by the
- * charger drivers directly.
- */
- if (curr.ocpc.active_chg_chip == CHARGER_PRIMARY)
-#endif
- r2 = charger_set_current(0, current);
- }
- if (r2 != EC_SUCCESS)
- problem(PR_SET_CURRENT, r2);
-
- if (voltage >= 0)
- r1 = charger_set_voltage(0, voltage);
- if (r1 != EC_SUCCESS)
- problem(PR_SET_VOLTAGE, r1);
-
-#ifdef CONFIG_OCPC
- /*
- * For OCPC systems, if the secondary charger is active, we need to
- * configure that charge IC as well. Note that if OCPC ever supports
- * more than 2 charger ICs, we'll need to refactor things a bit. The
- * following check should be comparing against CHARGER_PRIMARY and
- * config_secondary_charger should probably be config_auxiliary_charger
- * and take the active chgnum as a parameter.
- */
- if (curr.ocpc.active_chg_chip == CHARGER_SECONDARY) {
- if ((current >= 0) || (voltage >= 0))
- r3 = ocpc_config_secondary_charger(&curr.desired_input_current,
- &curr.ocpc,
- voltage, current);
- if (r3 != EC_SUCCESS)
- problem(PR_CFG_SEC_CHG, r3);
- }
-#endif /* CONFIG_OCPC */
-
- /*
- * Set the charge inhibit bit when possible as it appears to save
- * power in some cases (e.g. Nyan with BQ24735).
- */
- if (voltage > 0 || current > 0)
- r4 = charger_set_mode(0);
- else
- r4 = charger_set_mode(CHARGE_FLAG_INHIBIT_CHARGE);
- if (r4 != EC_SUCCESS)
- problem(PR_SET_MODE, r4);
-
- /*
- * Only update if the request worked, so we'll keep trying on failures.
- */
- if (r1 || r2)
- return r1 ? r1 : r2;
- if (IS_ENABLED(CONFIG_OCPC) && r3)
- return r3;
-
- if (IS_ENABLED(CONFIG_USB_PD_PREFER_MV) &&
- (prev_volt != voltage || prev_curr != current))
- charge_reset_stable_current();
-
- prev_volt = voltage;
- prev_curr = current;
-
- return EC_SUCCESS;
-}
-
-void chgstate_set_manual_current(int curr_ma)
-{
- if (curr_ma < 0)
- manual_current = -1;
- else
- manual_current = charger_closest_current(curr_ma);
-}
-
-void chgstate_set_manual_voltage(int volt_mv)
-{
- manual_voltage = charger_closest_voltage(volt_mv);
-}
-
-/* Force charging off before the battery is full. */
-static int set_chg_ctrl_mode(enum ec_charge_control_mode mode)
-{
- bool discharge_on_ac = false;
- int current, voltage;
- int rv;
-
- current = manual_current;
- voltage = manual_voltage;
-
- if (mode >= CHARGE_CONTROL_COUNT)
- return EC_ERROR_INVAL;
-
- if (mode == CHARGE_CONTROL_NORMAL) {
- current = -1;
- voltage = -1;
- } else {
- /* Changing mode is only meaningful if AC is present. */
- if (!curr.ac)
- return EC_ERROR_NOT_POWERED;
-
- if (mode == CHARGE_CONTROL_DISCHARGE) {
- if (!IS_ENABLED(CONFIG_CHARGER_DISCHARGE_ON_AC))
- return EC_ERROR_UNIMPLEMENTED;
- discharge_on_ac = true;
- } else if (mode == CHARGE_CONTROL_IDLE) {
- current = 0;
- voltage = 0;
- }
- }
-
- if (IS_ENABLED(CONFIG_CHARGER_DISCHARGE_ON_AC)) {
- rv = charger_discharge_on_ac(discharge_on_ac);
- if (rv != EC_SUCCESS)
- return rv;
- }
-
- /* Commit all atomically */
- chg_ctl_mode = mode;
- manual_current = current;
- manual_voltage = voltage;
-
- return EC_SUCCESS;
-}
-
-static inline int battery_too_hot(int batt_temp_c)
-{
- return (!(curr.batt.flags & BATT_FLAG_BAD_TEMPERATURE) &&
- (batt_temp_c > batt_info->discharging_max_c));
-}
-
-static inline int battery_too_cold_for_discharge(int batt_temp_c)
-{
- return (!(curr.batt.flags & BATT_FLAG_BAD_TEMPERATURE) &&
- (batt_temp_c < batt_info->discharging_min_c));
-}
-
-__attribute__((weak)) uint8_t board_set_battery_level_shutdown(void)
-{
- return BATTERY_LEVEL_SHUTDOWN;
-}
-
-/* True if we know the charge is too low, or we know the voltage is too low. */
-static inline int battery_too_low(void)
-{
- return ((!(curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) &&
- curr.batt.state_of_charge < battery_level_shutdown) ||
- (!(curr.batt.flags & BATT_FLAG_BAD_VOLTAGE) &&
- curr.batt.voltage <= batt_info->voltage_min));
-}
-
-__attribute__((weak))
-enum critical_shutdown board_critical_shutdown_check(
- struct charge_state_data *curr)
-{
-#ifdef CONFIG_BATTERY_CRITICAL_SHUTDOWN_CUT_OFF
- return CRITICAL_SHUTDOWN_CUTOFF;
-#elif defined(CONFIG_HIBERNATE)
- return CRITICAL_SHUTDOWN_HIBERNATE;
-#else
- return CRITICAL_SHUTDOWN_IGNORE;
-#endif
-}
-
-static int is_battery_critical(void)
-{
- int batt_temp_c = DECI_KELVIN_TO_CELSIUS(curr.batt.temperature);
-
- /*
- * TODO(crosbug.com/p/27642): The thermal loop should watch the battery
- * temp, so it can turn fans on.
- */
- if (battery_too_hot(batt_temp_c)) {
- CPRINTS("Batt too hot: %dC", batt_temp_c);
- return 1;
- }
-
- /* Note: the battery may run on AC without discharging when too cold */
- if (!curr.ac && battery_too_cold_for_discharge(batt_temp_c)) {
- CPRINTS("Batt too cold: %dC", batt_temp_c);
- return 1;
- }
-
- if (battery_too_low() && !curr.batt_is_charging) {
- CPRINTS("Low battery: %d%%, %dmV",
- curr.batt.state_of_charge, curr.batt.voltage);
- return 1;
- }
-
- return 0;
-}
-
- /*
- * If the battery is at extremely low charge (and discharging) or extremely
- * high temperature, the EC will notify the AP and start a timer. If the
- * critical condition is not corrected before the timeout expires, the EC
- * will shut down the AP (if the AP is not already off) and then optionally
- * hibernate or cut off battery.
- */
-static int shutdown_on_critical_battery(void)
-{
- if (!is_battery_critical()) {
- /* Reset shutdown warning time */
- shutdown_target_time.val = 0;
- return 0;
- }
-
- if (!shutdown_target_time.val) {
- /* Start count down timer */
- CPRINTS("Start shutdown due to critical battery");
- shutdown_target_time.val = get_time().val
- + CRITICAL_BATTERY_SHUTDOWN_TIMEOUT_US;
-#ifdef CONFIG_HOSTCMD_EVENTS
- if (!chipset_in_state(CHIPSET_STATE_ANY_OFF))
- host_set_single_event(EC_HOST_EVENT_BATTERY_SHUTDOWN);
-#endif
- return 1;
- }
-
- if (!timestamp_expired(shutdown_target_time, 0))
- return 1;
-
- /* Timer has expired */
- if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) {
- switch (board_critical_shutdown_check(&curr)) {
- case CRITICAL_SHUTDOWN_HIBERNATE:
- if (IS_ENABLED(CONFIG_HIBERNATE)) {
- if (power_get_state() == POWER_S3S5)
- sleep(1);
- CPRINTS("Hibernate due to critical battery");
- cflush();
- system_hibernate(0, 0);
- }
- break;
- case CRITICAL_SHUTDOWN_CUTOFF:
- if (power_get_state() == POWER_S3S5)
- sleep(1);
- CPRINTS("Cutoff due to critical battery");
- cflush();
- board_cut_off_battery();
- break;
- case CRITICAL_SHUTDOWN_IGNORE:
- default:
- break;
- }
- } else {
- /* Timeout waiting for AP to shut down, so kill it */
- CPRINTS(
- "charge force shutdown due to critical battery");
- chipset_force_shutdown(CHIPSET_SHUTDOWN_BATTERY_CRIT);
- }
-
- return 1;
-}
-
-/*
- * Send host events as the battery charge drops below certain thresholds.
- * We handle forced shutdown and other actions elsewhere; this is just for the
- * host events. We send these even if the AP is off, since the AP will read and
- * discard any events it doesn't care about the next time it wakes up.
- */
-static void notify_host_of_low_battery_charge(void)
-{
- /* We can't tell what the current charge is. Assume it's okay. */
- if (curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE)
- return;
-
-#ifdef CONFIG_HOSTCMD_EVENTS
- if (curr.batt.state_of_charge <= BATTERY_LEVEL_LOW &&
- prev_charge > BATTERY_LEVEL_LOW)
- host_set_single_event(EC_HOST_EVENT_BATTERY_LOW);
-
- if (curr.batt.state_of_charge <= BATTERY_LEVEL_CRITICAL &&
- prev_charge > BATTERY_LEVEL_CRITICAL)
- host_set_single_event(EC_HOST_EVENT_BATTERY_CRITICAL);
-#endif
-}
-
-static void set_charge_state(enum charge_state_v2 state)
-{
- prev_state = curr.state;
- curr.state = state;
-}
-
-static void notify_host_of_low_battery_voltage(void)
-{
-#ifdef CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE
- if ((curr.batt.flags & BATT_FLAG_BAD_VOLTAGE) ||
- chipset_in_state(CHIPSET_STATE_ANY_OFF))
- return;
-
- if (!uvp_throttle_start_time.val &&
- (curr.batt.voltage < BAT_LOW_VOLTAGE_THRESH)) {
- throttle_ap(THROTTLE_ON, THROTTLE_SOFT,
- THROTTLE_SRC_BAT_VOLTAGE);
- uvp_throttle_start_time = get_time();
- } else if (uvp_throttle_start_time.val &&
- (curr.batt.voltage < BAT_LOW_VOLTAGE_THRESH +
- BAT_UVP_HYSTERESIS)) {
- /*
- * Reset the timer when we are not sure if VBAT can stay
- * above BAT_LOW_VOLTAGE_THRESH after we stop throttling.
- */
- uvp_throttle_start_time = get_time();
- } else if (uvp_throttle_start_time.val &&
- (get_time().val > uvp_throttle_start_time.val +
- BAT_UVP_TIMEOUT_US)) {
- throttle_ap(THROTTLE_OFF, THROTTLE_SOFT,
- THROTTLE_SRC_BAT_VOLTAGE);
- uvp_throttle_start_time.val = 0;
- }
-#endif
-}
-
-static void notify_host_of_over_current(struct batt_params *batt)
-{
-#ifdef CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT
- static timestamp_t ocp_throttle_start_time;
-
- if (batt->flags & BATT_FLAG_BAD_CURRENT)
- return;
-
- if ((!ocp_throttle_start_time.val &&
- (batt->current < -BAT_MAX_DISCHG_CURRENT)) ||
- (ocp_throttle_start_time.val &&
- (batt->current < -BAT_MAX_DISCHG_CURRENT + BAT_OCP_HYSTERESIS))) {
- ocp_throttle_start_time = get_time();
- throttle_ap(THROTTLE_ON, THROTTLE_SOFT,
- THROTTLE_SRC_BAT_DISCHG_CURRENT);
- } else if (ocp_throttle_start_time.val &&
- (get_time().val > ocp_throttle_start_time.val +
- BAT_OCP_TIMEOUT_US)) {
- /*
- * Clear the timer and notify AP to stop throttling if
- * we haven't seen over current for BAT_OCP_TIMEOUT_US.
- */
- ocp_throttle_start_time.val = 0;
- throttle_ap(THROTTLE_OFF, THROTTLE_SOFT,
- THROTTLE_SRC_BAT_DISCHG_CURRENT);
- }
-#endif
-}
-
-const struct batt_params *charger_current_battery_params(void)
-{
- return &curr.batt;
-}
-
-/* Determine if the battery is outside of allowable temperature range */
-static int battery_outside_charging_temperature(void)
-{
- const struct battery_info *batt_info = battery_get_info();
- int batt_temp_c = DECI_KELVIN_TO_CELSIUS(curr.batt.temperature);
- int max_c, min_c;
-
- if (curr.batt.flags & BATT_FLAG_BAD_TEMPERATURE)
- return 0;
-
- if((curr.batt.desired_voltage == 0) &&
- (curr.batt.desired_current == 0)){
- max_c = batt_info->start_charging_max_c;
- min_c = batt_info->start_charging_min_c;
- } else {
- max_c = batt_info->charging_max_c;
- min_c = batt_info->charging_min_c;
- }
-
-
- if ((batt_temp_c >= max_c) ||
- (batt_temp_c <= min_c)) {
- return 1;
- }
- return 0;
-}
-
-static void sustain_battery_soc(void)
-{
- enum ec_charge_control_mode mode = get_chg_ctrl_mode();
- int soc;
- int rv;
-
- /* If either AC or battery is not present, nothing to do. */
- if (!curr.ac || curr.batt.is_present != BP_YES
- || !battery_sustainer_enabled())
- return;
-
- soc = charge_get_display_charge() / 10;
-
- /*
- * When lower < upper, the sustainer discharges using DISCHARGE. When
- * lower == upper, the sustainer discharges using IDLE. The following
- * switch statement handle both cases but in reality either DISCHARGE
- * or IDLE is used but not both.
- */
- switch (mode) {
- case CHARGE_CONTROL_NORMAL:
- /* Going up */
- if (sustain_soc.upper < soc)
- mode = sustain_soc.upper == sustain_soc.lower ?
- CHARGE_CONTROL_IDLE : CHARGE_CONTROL_DISCHARGE;
- break;
- case CHARGE_CONTROL_IDLE:
- /* Discharging naturally */
- if (soc < sustain_soc.lower)
- mode = CHARGE_CONTROL_NORMAL;
- break;
- case CHARGE_CONTROL_DISCHARGE:
- /* Discharging actively. */
- if (soc < sustain_soc.lower)
- mode = CHARGE_CONTROL_NORMAL;
- break;
- default:
- return;
- }
-
- if (mode == get_chg_ctrl_mode())
- return;
-
- rv = set_chg_ctrl_mode(mode);
- CPRINTS("%s: %s control mode to %s",
- __func__, rv == EC_SUCCESS ? "Switched" : "Failed to switch",
- mode_text[mode]);
-}
-
-/*****************************************************************************/
-/* Hooks */
-void charger_init(void)
-{
- /* Initialize current state */
- memset(&curr, 0, sizeof(curr));
- curr.batt.is_present = BP_NOT_SURE;
- /* Manual voltage/current set to off */
- manual_voltage = -1;
- manual_current = -1;
- /*
- * Other tasks read the params like state_of_charge at the beginning of
- * their tasks. Make them ready first.
- */
- battery_get_params(&curr.batt);
-
- battery_sustainer_disable();
-}
-DECLARE_HOOK(HOOK_INIT, charger_init, HOOK_PRIO_DEFAULT);
-
-/* Wake up the task when something important happens */
-static void charge_wakeup(void)
-{
- task_wake(TASK_ID_CHARGER);
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, charge_wakeup, HOOK_PRIO_DEFAULT);
-DECLARE_HOOK(HOOK_AC_CHANGE, charge_wakeup, HOOK_PRIO_DEFAULT);
-
-#ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT
-/* Reset the base on S5->S0 transition. */
-DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_base_reset, HOOK_PRIO_DEFAULT);
-#endif
-
-#ifdef CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE
-static void bat_low_voltage_throttle_reset(void)
-{
- uvp_throttle_start_time.val = 0;
-}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN,
- bat_low_voltage_throttle_reset,
- HOOK_PRIO_DEFAULT);
-#endif
-
-static int get_desired_input_current(enum battery_present batt_present,
- const struct charger_info * const info)
-{
- if (batt_present == BP_YES || system_is_locked() || base_connected) {
-#ifdef CONFIG_CHARGE_MANAGER
- int ilim = charge_manager_get_charger_current();
- return ilim == CHARGE_CURRENT_UNINITIALIZED ?
- CHARGE_CURRENT_UNINITIALIZED :
- MAX(CONFIG_CHARGER_INPUT_CURRENT, ilim);
-#else
- return CONFIG_CHARGER_INPUT_CURRENT;
-#endif
- } else {
-#ifdef CONFIG_USB_POWER_DELIVERY
- return MIN(PD_MAX_CURRENT_MA, info->input_current_max);
-#else
- return info->input_current_max;
-#endif
- }
-}
-
-static void wakeup_battery(int *need_static)
-{
- if (battery_seems_dead || battery_is_cut_off()) {
- /* It's dead, do nothing */
- set_charge_state(ST_IDLE);
- curr.requested_voltage = 0;
- curr.requested_current = 0;
- } else if (curr.state == ST_PRECHARGE
- && (get_time().val > precharge_start_time.val +
- PRECHARGE_TIMEOUT_US)) {
- /* We've tried long enough, give up */
- CPRINTS("battery seems to be dead");
- battery_seems_dead = 1;
- set_charge_state(ST_IDLE);
- curr.requested_voltage = 0;
- curr.requested_current = 0;
- } else {
- /* See if we can wake it up */
- if (curr.state != ST_PRECHARGE) {
- CPRINTS("try to wake battery");
- precharge_start_time = get_time();
- *need_static = 1;
- }
- set_charge_state(ST_PRECHARGE);
- curr.requested_voltage = batt_info->voltage_max;
- curr.requested_current = batt_info->precharge_current;
- }
-}
-
-static void revive_battery(int *need_static)
-{
- if (IS_ENABLED(CONFIG_BATTERY_REQUESTS_NIL_WHEN_DEAD)
- && curr.requested_voltage == 0
- && curr.requested_current == 0
- && curr.batt.state_of_charge == 0) {
- /*
- * Battery is dead, give precharge current
- * TODO (crosbug.com/p/29467): remove this workaround
- * for dead battery that requests no voltage/current
- */
- curr.requested_voltage = batt_info->voltage_max;
- curr.requested_current = batt_info->precharge_current;
- } else if (IS_ENABLED(CONFIG_BATTERY_REVIVE_DISCONNECT)
- && curr.requested_voltage == 0
- && curr.requested_current == 0
- && battery_seems_disconnected) {
- /*
- * Battery is in disconnect state. Apply a
- * current to kick it out of this state.
- */
- CPRINTS("found battery in disconnect state");
- curr.requested_voltage = batt_info->voltage_max;
- curr.requested_current = batt_info->precharge_current;
- } else if (curr.state == ST_PRECHARGE
- || battery_seems_dead || battery_was_removed) {
- CPRINTS("battery woke up");
- /* Update the battery-specific values */
- batt_info = battery_get_info();
- *need_static = 1;
- }
-
- battery_seems_dead = battery_was_removed = 0;
-}
-
-/* Main loop */
-void charger_task(void *u)
-{
- int sleep_usec;
- int battery_critical;
- int need_static = 1;
- const struct charger_info * const info = charger_get_info();
- int prev_plt_and_desired_mw;
- int chgnum = 0;
-
- /* Get the battery-specific values */
- batt_info = battery_get_info();
-
- prev_ac = prev_charge = prev_disp_charge = -1;
- chg_ctl_mode = CHARGE_CONTROL_NORMAL;
- shutdown_target_time.val = 0UL;
- battery_seems_dead = 0;
-#ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT
- base_responsive = 0;
- curr.input_voltage = CHARGE_VOLTAGE_UNINITIALIZED;
- battery_dynamic[BATT_IDX_BASE].flags = EC_BATT_FLAG_INVALID_DATA;
- charge_base = -1;
-#endif
-#ifdef CONFIG_OCPC
- ocpc_init(&curr.ocpc);
- charge_set_active_chg_chip(CHARGE_PORT_NONE);
-#endif /* CONFIG_OCPC */
-
- /*
- * If system is not locked and we don't have a battery to live on,
- * then use max input current limit so that we can pull as much power
- * as needed.
- */
- prev_bp = BP_NOT_INIT;
- curr.desired_input_current = get_desired_input_current(
- curr.batt.is_present, info);
-
- if (IS_ENABLED(CONFIG_USB_PD_PREFER_MV)) {
- /* init battery desired power */
- desired_mw =
- curr.batt.desired_current * curr.batt.desired_voltage;
- /*
- * Battery charging current needs time to be stable when a
- * new charge happens. Start the timer so we can evaluate the
- * stable current when timeout.
- */
- charge_reset_stable_current();
- }
-
- battery_level_shutdown = board_set_battery_level_shutdown();
-
- while (1) {
-
- /* Let's see what's going on... */
- curr.ts = get_time();
- sleep_usec = 0;
- problems_exist = 0;
- battery_critical = 0;
- curr.ac = extpower_is_present();
-#ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT
- /*
- * When base is powering the system, make sure curr.ac stays 0.
- * TODO(b:71723024): Fix extpower_is_present() in hardware
- * instead.
- */
- if (base_responsive && prev_current_base < 0)
- curr.ac = 0;
-
- /* System is off: if AC gets connected, reset the base. */
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF) &&
- !prev_ac && curr.ac)
- board_base_reset();
-#endif
- if (curr.ac != prev_ac) {
- /*
- * We've noticed a change in AC presence, let the board
- * know.
- */
- board_check_extpower();
- if (curr.ac) {
- /*
- * Some chargers are unpowered when the AC is
- * off, so we'll reinitialize it when AC
- * comes back and set the input current limit.
- * Try again if it fails.
- */
- int rv = charger_post_init();
-
- if (rv != EC_SUCCESS) {
- problem(PR_POST_INIT, rv);
- } else if (curr.desired_input_current !=
- CHARGE_CURRENT_UNINITIALIZED) {
- rv = charger_set_input_current_limit(
- chgnum,
- curr.desired_input_current);
- if (rv != EC_SUCCESS)
- problem(PR_SET_INPUT_CURR, rv);
- }
-
- if (rv == EC_SUCCESS)
- prev_ac = curr.ac;
- } else {
- /* Some things are only meaningful on AC */
- set_chg_ctrl_mode(CHARGE_CONTROL_NORMAL);
- battery_seems_dead = 0;
- prev_ac = curr.ac;
-
- /*
- * b/187967523, we should clear charge current,
- * otherwise it will effect typeC output.this
- * should be ok for all chargers.
- */
- charger_set_current(chgnum, 0);
- }
- }
-
-#ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT
- update_base_battery_info();
-#endif
-
- charger_get_params(&curr.chg);
- battery_get_params(&curr.batt);
-#ifdef CONFIG_OCPC
- if (curr.ac)
- ocpc_get_adcs(&curr.ocpc);
-#endif /* CONFIG_OCPC */
-
- if (prev_bp != curr.batt.is_present) {
- prev_bp = curr.batt.is_present;
-
- /* Update battery info due to change of battery */
- batt_info = battery_get_info();
- need_static = 1;
-
- curr.desired_input_current =
- get_desired_input_current(prev_bp, info);
- if (curr.desired_input_current !=
- CHARGE_CURRENT_UNINITIALIZED)
- charger_set_input_current_limit(chgnum,
- curr.desired_input_current);
- hook_notify(HOOK_BATTERY_SOC_CHANGE);
- }
-
- battery_validate_params(&curr.batt);
-
- notify_host_of_over_current(&curr.batt);
-
- /* battery current stable now, saves the current. */
- if (IS_ENABLED(CONFIG_USB_PD_PREFER_MV) &&
- get_time().val > stable_ts.val && curr.batt.current >= 0)
- stable_current = curr.batt.current;
-
- /*
- * Now decide what we want to do about it. We'll normally just
- * pass along whatever the battery wants to the charger. Note
- * that if battery_get_params() can't get valid values from the
- * battery it uses (0, 0), which is probably safer than blindly
- * applying power to a battery we can't talk to.
- */
- if (curr.batt.flags & (BATT_FLAG_BAD_DESIRED_VOLTAGE |
- BATT_FLAG_BAD_DESIRED_CURRENT)) {
- curr.requested_voltage = 0;
- curr.requested_current = 0;
- } else {
- curr.requested_voltage = curr.batt.desired_voltage;
- curr.requested_current = curr.batt.desired_current;
- }
-
- /* If we *know* there's no battery, wait for one to appear. */
- if (curr.batt.is_present == BP_NO) {
- if (!curr.ac)
- CPRINTS("running with no battery and no AC");
- set_charge_state(ST_IDLE);
- curr.batt_is_charging = 0;
- battery_was_removed = 1;
- goto wait_for_it;
- }
-
- /*
- * If we had trouble talking to the battery or the charger, we
- * should probably do nothing for a bit, and if it doesn't get
- * better then flag it as an error.
- */
- if (curr.chg.flags & CHG_FLAG_BAD_ANY)
- problem(PR_CHG_FLAGS, curr.chg.flags);
- if (curr.batt.flags & BATT_FLAG_BAD_ANY)
- problem(PR_BATT_FLAGS, curr.batt.flags);
-
- /*
- * If AC is present, check if input current is sufficient to
- * actually charge battery.
- */
- curr.batt_is_charging = curr.ac && (curr.batt.current >= 0);
-
- /* Don't let the battery hurt itself. */
- battery_critical = shutdown_on_critical_battery();
-
- if (!curr.ac) {
- set_charge_state(ST_DISCHARGE);
- goto wait_for_it;
- }
-
- /* Okay, we're on AC and we should have a battery. */
-
- /* Used for factory tests. */
- if (get_chg_ctrl_mode() != CHARGE_CONTROL_NORMAL) {
- set_charge_state(ST_IDLE);
- goto wait_for_it;
- }
-
- /* If the battery is not responsive, try to wake it up. */
- if (!(curr.batt.flags & BATT_FLAG_RESPONSIVE)) {
- wakeup_battery(&need_static);
- goto wait_for_it;
- }
-
- /* The battery is responding. Yay. Try to use it. */
-
- /*
- * Always check the disconnect state. This is because
- * the battery disconnect state is one of the items used
- * to decide whether or not to leave safe mode.
- */
- battery_seems_disconnected =
- battery_get_disconnect_state() == BATTERY_DISCONNECTED;
-
- revive_battery(&need_static);
-
- set_charge_state(ST_CHARGE);
-
-wait_for_it:
- if (IS_ENABLED(CONFIG_CHARGER_PROFILE_OVERRIDE)
- && get_chg_ctrl_mode() == CHARGE_CONTROL_NORMAL) {
- sleep_usec = charger_profile_override(&curr);
- if (sleep_usec < 0)
- problem(PR_CUSTOM, sleep_usec);
- }
-
- if (IS_ENABLED(CONFIG_BATTERY_CHECK_CHARGE_TEMP_LIMITS)
- && battery_outside_charging_temperature()) {
- curr.requested_current = 0;
- curr.requested_voltage = 0;
- curr.batt.flags &= ~BATT_FLAG_WANT_CHARGE;
- if (curr.state != ST_DISCHARGE)
- curr.state = ST_IDLE;
- }
-
-#ifdef CONFIG_CHARGE_MANAGER
- if (curr.batt.state_of_charge >=
- CONFIG_CHARGE_MANAGER_BAT_PCT_SAFE_MODE_EXIT &&
- !battery_seems_disconnected) {
- /*
- * Sometimes the fuel gauge will report that it has
- * sufficient state of charge and remaining capacity,
- * but in actuality it doesn't. When the EC sees that
- * information, it trusts it and leaves charge manager
- * safe mode. Doing so will allow CHARGE_PORT_NONE to
- * be selected, thereby cutting off the input FETs.
- * When the battery cannot provide the charge it claims,
- * the system loses power, shuts down, and the battery
- * is not charged even though the charger is plugged in.
- * By waiting 500ms, we can avoid the selection of
- * CHARGE_PORT_NONE around init time and not cut off the
- * input FETs.
- */
- msleep(500);
- charge_manager_leave_safe_mode();
- }
-#endif
-
- /* Keep the AP informed */
- if (need_static)
- need_static = update_static_battery_info();
- /* Wait on the dynamic info until the static info is good. */
- if (!need_static)
- update_dynamic_battery_info();
- notify_host_of_low_battery_charge();
- notify_host_of_low_battery_voltage();
-
- /* And the EC console */
- is_full = calc_is_full();
-
- /* Run battery sustainer (no-op if not applicable). */
- sustain_battery_soc();
-
- if ((!(curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) &&
- curr.batt.state_of_charge != prev_charge) ||
-#ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT
- (charge_base != prev_charge_base) ||
-#endif
- (is_full != prev_full) ||
- (curr.state != prev_state) ||
- (charge_get_display_charge() != prev_disp_charge)) {
- show_charging_progress();
- prev_charge = curr.batt.state_of_charge;
- prev_disp_charge = charge_get_display_charge();
-#ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT
- prev_charge_base = charge_base;
-#endif
- hook_notify(HOOK_BATTERY_SOC_CHANGE);
- }
- prev_full = is_full;
-
-#ifndef CONFIG_CHARGER_MAINTAIN_VBAT
- /* Turn charger off if it's not needed */
- if (curr.state == ST_IDLE || curr.state == ST_DISCHARGE) {
- curr.requested_voltage = 0;
- curr.requested_current = 0;
- }
-#endif
-
- /* Apply external limits */
- if (curr.requested_current > user_current_limit)
- curr.requested_current = user_current_limit;
-
- /* Round to valid values */
- curr.requested_voltage =
- charger_closest_voltage(curr.requested_voltage);
- curr.requested_current =
- charger_closest_current(curr.requested_current);
-
- /* Charger only accpets request when AC is on. */
- if (curr.ac) {
- /*
- * Some batteries would wake up after cut-off if we keep
- * charging it. Thus, we only charge when AC is on and
- * battery is not cut off yet.
- */
- if (battery_is_cut_off()) {
- curr.requested_voltage = 0;
- curr.requested_current = 0;
- }
- /*
- * As a safety feature, some chargers will stop
- * charging if we don't communicate with it frequently
- * enough. In manual mode, we'll just tell it what it
- * knows.
- */
- else {
- if (manual_voltage != -1)
- curr.requested_voltage = manual_voltage;
- if (manual_current != -1)
- curr.requested_current = manual_current;
- }
- } else {
-#ifndef CONFIG_CHARGER_MAINTAIN_VBAT
- curr.requested_voltage = charger_closest_voltage(
- curr.batt.voltage + info->voltage_step);
- curr.requested_current = -1;
-#endif
-#ifdef CONFIG_EC_EC_COMM_BATTERY_SERVER
- /*
- * On EC-EC server, do not charge if curr.ac is 0: there
- * might still be some external power available but we
- * do not want to use it for charging.
- */
- curr.requested_current = 0;
-#endif
- }
-
-#ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT
- charge_allocate_input_current_limit();
-#else
- charge_request(curr.requested_voltage, curr.requested_current);
-#endif
-
- /* How long to sleep? */
- if (problems_exist)
- /* If there are errors, don't wait very long. */
- sleep_usec = CHARGE_POLL_PERIOD_SHORT;
- else if (sleep_usec <= 0) {
- /* default values depend on the state */
- if (!curr.ac &&
- (curr.state == ST_IDLE ||
- curr.state == ST_DISCHARGE)) {
-#ifdef CONFIG_CHARGER_OTG
- int output_current = curr.output_current;
-#else
- int output_current = 0;
-#endif
- /*
- * If AP is off and we do not provide power, we
- * can sleep a long time.
- */
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF |
- CHIPSET_STATE_ANY_SUSPEND)
- && output_current == 0)
- sleep_usec =
- CHARGE_POLL_PERIOD_VERY_LONG;
- else
- /* Discharging, not too urgent */
- sleep_usec = CHARGE_POLL_PERIOD_LONG;
- } else {
- /* AC present, so pay closer attention */
- sleep_usec = CHARGE_POLL_PERIOD_CHARGE;
- }
- }
-
- if (IS_ENABLED(CONFIG_USB_PD_PREFER_MV)) {
- int is_pd_supply = charge_manager_get_supplier() ==
- CHARGE_SUPPLIER_PD;
- int port = charge_manager_get_active_charge_port();
- int bat_spec_desired_mw = curr.batt.desired_current *
- curr.batt.desired_voltage /
- 1000;
-
- /*
- * save the previous plt_and_desired_mw, since it
- * will be updated below
- */
- prev_plt_and_desired_mw =
- charge_get_plt_plus_bat_desired_mw();
-
- /*
- * Update desired power by the following rules:
- * 1. If the battery is not charging with PD, we reset
- * the desired_mw to the battery spec. The actual
- * desired_mw will be evaluated when it starts charging
- * with PD again.
- * 2. If the battery SoC under battery's constant
- * voltage percent (this is a rough value that can be
- * applied to most batteries), the battery can fully
- * sink the power, the desired power should be the
- * same as the battery spec, and we don't need to use
- * evaluated value stable_current.
- * 3. If the battery SoC is above battery's constant
- * voltage percent, the real battery desired charging
- * power will decrease slowly and so does the charging
- * current. We can evaluate the battery desired power
- * by the product of stable_current and battery voltage.
- */
- if (!is_pd_supply)
- desired_mw = bat_spec_desired_mw;
- else if (curr.batt.state_of_charge < pd_pref_config.cv)
- desired_mw = bat_spec_desired_mw;
- else if (stable_current != CHARGE_CURRENT_UNINITIALIZED)
- desired_mw = curr.batt.voltage *
- stable_current / 1000;
-
- /* if the plt_and_desired_mw changes, re-evaluate PDO */
- if (is_pd_supply &&
- prev_plt_and_desired_mw !=
- charge_get_plt_plus_bat_desired_mw())
- pd_set_new_power_request(port);
- }
-
- /* Adjust for time spent in this loop */
- sleep_usec -= (int)(get_time().val - curr.ts.val);
- if (sleep_usec < CHARGE_MIN_SLEEP_USEC)
- sleep_usec = CHARGE_MIN_SLEEP_USEC;
- else if (sleep_usec > CHARGE_MAX_SLEEP_USEC)
- sleep_usec = CHARGE_MAX_SLEEP_USEC;
-
- /*
- * If battery is critical, ensure that the sleep time is not
- * very long since we might want to hibernate or cut-off
- * battery sooner.
- */
- if (battery_critical &&
- (sleep_usec > CRITICAL_BATTERY_SHUTDOWN_TIMEOUT_US))
- sleep_usec = CRITICAL_BATTERY_SHUTDOWN_TIMEOUT_US;
-
- task_wait_event(sleep_usec);
- }
-}
-
-
-/*****************************************************************************/
-/* Exported functions */
-
-int charge_want_shutdown(void)
-{
- return (curr.state == ST_DISCHARGE) &&
- !(curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) &&
- (curr.batt.state_of_charge < battery_level_shutdown);
-}
-
-int charge_prevent_power_on(int power_button_pressed)
-{
- int prevent_power_on = 0;
- struct batt_params params;
- struct batt_params *current_batt_params = &curr.batt;
-#ifdef CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON
- static int automatic_power_on = 1;
-#endif
-
- /* If battery params seem uninitialized then retrieve them */
- if (current_batt_params->is_present == BP_NOT_SURE) {
- battery_get_params(&params);
- current_batt_params = &params;
- }
-
-#ifdef CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON
-
- /*
- * Remember that a power button was pressed, and assume subsequent
- * power-ups are user-requested and non-automatic.
- */
- if (power_button_pressed)
- automatic_power_on = 0;
- /*
- * Require a minimum battery level to power on and ensure that the
- * battery can provide power to the system.
- */
- if (current_batt_params->is_present != BP_YES ||
-#ifdef CONFIG_BATTERY_MEASURE_IMBALANCE
- (current_batt_params->flags & BATT_FLAG_IMBALANCED_CELL &&
- current_batt_params->state_of_charge <
- CONFIG_CHARGER_MIN_BAT_PCT_IMBALANCED_POWER_ON) ||
-#endif
-#ifdef CONFIG_BATTERY_REVIVE_DISCONNECT
- battery_get_disconnect_state() != BATTERY_NOT_DISCONNECTED ||
-#endif
- current_batt_params->state_of_charge <
- CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON)
- prevent_power_on = 1;
-
-#if defined(CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON) && \
- defined(CONFIG_CHARGE_MANAGER)
- /* However, we can power on if a sufficient charger is present. */
- if (prevent_power_on) {
- if (charge_manager_get_power_limit_uw() >=
- CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000)
- prevent_power_on = 0;
-#if defined(CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT) && \
- defined(CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON_WITH_AC)
- else if (charge_manager_get_power_limit_uw() >=
- CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON_WITH_BATT * 1000
-#ifdef CONFIG_BATTERY_REVIVE_DISCONNECT
- && battery_get_disconnect_state() ==
- BATTERY_NOT_DISCONNECTED
-#endif
- && (current_batt_params->state_of_charge >=
- CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON_WITH_AC))
- prevent_power_on = 0;
-#endif
- }
-#endif /* CONFIG_CHARGE_MANAGER && CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON */
-
- /*
- * Factory override: Always allow power on if WP is disabled,
- * except when auto-power-on at EC startup and the battery
- * is physically present.
- */
- prevent_power_on &= (system_is_locked() || (automatic_power_on
-#ifdef CONFIG_BATTERY_HW_PRESENT_CUSTOM
- && battery_hw_present() == BP_YES
-#endif
- ));
-#endif /* CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON */
-
-#ifdef CONFIG_CHARGE_MANAGER
- /* Always prevent power on until charge current is initialized */
- if (extpower_is_present() &&
- (charge_manager_get_charger_current() ==
- CHARGE_CURRENT_UNINITIALIZED))
- prevent_power_on = 1;
-#ifdef CONFIG_BATTERY_HW_PRESENT_CUSTOM
- /*
- * If battery is NOT physically present then prevent power on until
- * a sufficient charger is present.
- */
- if (extpower_is_present() && battery_hw_present() == BP_NO
-#ifdef CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON
- && charge_manager_get_power_limit_uw() <
- CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON * 1000
-#endif /* CONFIG_CHARGER_MIN_POWER_MW_FOR_POWER_ON */
- )
- prevent_power_on = 1;
-#endif /* CONFIG_BATTERY_HW_PRESENT_CUSTOM */
-#endif /* CONFIG_CHARGE_MANAGER */
-
- /*
- * Prevent power on if there is no battery nor ac power. This
- * happens when the servo is powering the EC to flash it. Only include
- * this logic for boards in initial bring up phase since this won't
- * happen for released boards.
- */
-#ifdef CONFIG_SYSTEM_UNLOCKED
- if (!current_batt_params->is_present && !curr.ac)
- prevent_power_on = 1;
-#endif /* CONFIG_SYSTEM_UNLOCKED */
-
- return prevent_power_on;
-}
-
-static int battery_near_full(void)
-{
- if (charge_get_percent() < BATTERY_LEVEL_NEAR_FULL)
- return 0;
-
-#ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT
- if (charge_base > -1 && charge_base < BATTERY_LEVEL_NEAR_FULL)
- return 0;
-#endif
-
- return 1;
-}
-
-enum charge_state charge_get_state(void)
-{
- switch (curr.state) {
- case ST_IDLE:
- if (battery_seems_dead || curr.batt.is_present == BP_NO)
- return PWR_STATE_ERROR;
- return PWR_STATE_IDLE;
- case ST_DISCHARGE:
-#ifdef CONFIG_PWR_STATE_DISCHARGE_FULL
- if (battery_near_full())
- return PWR_STATE_DISCHARGE_FULL;
- else
-#endif
- return PWR_STATE_DISCHARGE;
- case ST_CHARGE:
- /* The only difference here is what the LEDs display. */
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER) &&
- charge_manager_get_active_charge_port() == CHARGE_PORT_NONE)
- return PWR_STATE_DISCHARGE;
- else if (battery_near_full())
- return PWR_STATE_CHARGE_NEAR_FULL;
- else
- return PWR_STATE_CHARGE;
- case ST_PRECHARGE:
- /* we're in battery discovery mode */
- return PWR_STATE_IDLE;
- default:
- /* Anything else can be considered an error for LED purposes */
- return PWR_STATE_ERROR;
- }
-}
-
-uint32_t charge_get_flags(void)
-{
- uint32_t flags = 0;
-
- if (get_chg_ctrl_mode() != CHARGE_CONTROL_NORMAL)
- flags |= CHARGE_FLAG_FORCE_IDLE;
- if (curr.ac)
- flags |= CHARGE_FLAG_EXTERNAL_POWER;
- if (curr.batt.flags & BATT_FLAG_RESPONSIVE)
- flags |= CHARGE_FLAG_BATT_RESPONSIVE;
-
- return flags;
-}
-
-int charge_get_percent(void)
-{
- /*
- * Since there's no way to indicate an error to the caller, we'll just
- * return the last known value. Even if we've never been able to talk
- * to the battery, that'll be zero, which is probably as good as
- * anything.
- */
- return is_full ? 100 : curr.batt.state_of_charge;
-}
-
-test_mockable int charge_get_display_charge(void)
-{
- return curr.batt.display_charge;
-}
-
-int charge_get_battery_temp(int idx, int *temp_ptr)
-{
- if (curr.batt.flags & BATT_FLAG_BAD_TEMPERATURE)
- return EC_ERROR_UNKNOWN;
-
- /* Battery temp is 10ths of degrees K, temp wants degrees K */
- *temp_ptr = curr.batt.temperature / 10;
- return EC_SUCCESS;
-}
-
-__overridable int charge_is_consuming_full_input_current(void)
-{
- int chg_pct = charge_get_percent();
-
- return chg_pct > 2 && chg_pct < 95;
-}
-
-#ifdef CONFIG_CHARGER_OTG
-int charge_set_output_current_limit(int chgnum, int ma, int mv)
-{
- int ret;
- int enable = ma > 0;
-
- if (enable) {
- ret = charger_set_otg_current_voltage(chgnum, ma, mv);
- if (ret != EC_SUCCESS)
- return ret;
- }
-
- ret = charger_enable_otg_power(chgnum, enable);
- if (ret != EC_SUCCESS)
- return ret;
-
- /* If we start/stop providing power, wake the charger task. */
- if ((curr.output_current == 0 && enable) ||
- (curr.output_current > 0 && !enable))
- task_wake(TASK_ID_CHARGER);
-
- curr.output_current = ma;
-
- return EC_SUCCESS;
-}
-#endif
-
-int charge_set_input_current_limit(int ma, int mv)
-{
- __maybe_unused int chgnum = 0;
-
- if (IS_ENABLED(CONFIG_OCPC))
- chgnum = charge_get_active_chg_chip();
-#ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT
- curr.input_voltage = mv;
-#endif
- /*
- * If battery is not present, we are not locked, and base is not
- * connected then allow system to pull as much input current as needed.
- * Yes, we might overcurrent the charger but this is no worse than
- * browning out due to insufficient input current.
- */
- if (curr.batt.is_present != BP_YES && !system_is_locked() &&
- !base_connected) {
-
- int prev_input = 0;
-
- charger_get_input_current_limit(chgnum, &prev_input);
-
-#ifdef CONFIG_USB_POWER_DELIVERY
-#if ((PD_MAX_POWER_MW * 1000) / PD_MAX_VOLTAGE_MV != PD_MAX_CURRENT_MA)
- /*
- * If battery is not present, input current is set to
- * PD_MAX_CURRENT_MA. If the input power set is greater than
- * the maximum allowed system power, system might get damaged.
- * Hence, limit the input current to meet maximum allowed
- * input system power.
- */
-
- if (mv > 0 && mv * curr.desired_input_current >
- PD_MAX_POWER_MW * 1000)
- ma = (PD_MAX_POWER_MW * 1000) / mv;
- /*
- * If the active charger has already been initialized to at
- * least this current level, nothing left to do.
- */
- else if (prev_input >= ma)
- return EC_SUCCESS;
-#else
- if (prev_input >= ma)
- return EC_SUCCESS;
-#endif
- /*
- * If the current needs lowered due to PD max power
- * considerations, or needs raised for the selected active
- * charger chip, fall through to set.
- */
-#endif /* CONFIG_USB_POWER_DELIVERY */
- }
-
-#ifdef CONFIG_CHARGER_MAX_INPUT_CURRENT
- /* Limit input current limit to max limit for this board */
- ma = MIN(ma, CONFIG_CHARGER_MAX_INPUT_CURRENT);
-#endif
- curr.desired_input_current = ma;
-#ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT
- /* Wake up charger task to allocate current between lid and base. */
- charge_wakeup();
- return EC_SUCCESS;
-#else
- return charger_set_input_current_limit(chgnum, ma);
-#endif
-}
-
-#ifdef CONFIG_OCPC
-void charge_set_active_chg_chip(int idx)
-{
- ASSERT(idx < (int)board_get_charger_chip_count());
-
- if (idx == curr.ocpc.active_chg_chip)
- return;
-
- CPRINTS("Act Chg: %d", idx);
- curr.ocpc.active_chg_chip = idx;
-}
-#endif /* CONFIG_OCPC */
-
-int charge_get_active_chg_chip(void)
-{
-#ifdef CONFIG_OCPC
- return curr.ocpc.active_chg_chip;
-#else
- return 0;
-#endif
-}
-
-#ifdef CONFIG_USB_PD_PREFER_MV
-bool charge_is_current_stable(void)
-{
- return get_time().val >= stable_ts.val;
-}
-
-int charge_get_plt_plus_bat_desired_mw(void)
-{
- /*
- * Ideally, the system consuming power could be evaluated by
- * "IBus * VBus - battery charging power". But in practice,
- * most charger drivers don't implement IBUS ADC reading,
- * so we use system PLT instead as an alterntaive approach.
- */
- return pd_pref_config.plt_mw + desired_mw;
-}
-
-int charge_get_stable_current(void)
-{
- return stable_current;
-}
-
-void charge_set_stable_current(int ma)
-{
- stable_current = ma;
-}
-
-void charge_reset_stable_current_us(uint64_t us)
-{
- timestamp_t now = get_time();
-
- if (stable_ts.val < now.val + us)
- stable_ts.val = now.val + us;
-
- stable_current = CHARGE_CURRENT_UNINITIALIZED;
-}
-
-void charge_reset_stable_current(void)
-{
- /* it takes 8 to 10 seconds to stabilize battery current in practice */
- charge_reset_stable_current_us(10 * SECOND);
-}
-#endif
-
-#ifdef CONFIG_OCPC
-void trigger_ocpc_reset(void)
-{
- ocpc_reset(&curr.ocpc);
-}
-#endif
-
-/*****************************************************************************/
-/* Host commands */
-
-static enum ec_status
-charge_command_charge_control(struct host_cmd_handler_args *args)
-{
- const struct ec_params_charge_control *p = args->params;
- struct ec_response_charge_control *r = args->response;
- int rv;
-
- if (args->version >= 2) {
- if (p->cmd == EC_CHARGE_CONTROL_CMD_SET) {
- if (p->mode == CHARGE_CONTROL_NORMAL) {
- rv = battery_sustainer_set(
- p->sustain_soc.lower,
- p->sustain_soc.upper);
- if (rv == EC_RES_UNAVAILABLE)
- return EC_RES_UNAVAILABLE;
- if (rv)
- return EC_RES_INVALID_PARAM;
- } else {
- battery_sustainer_disable();
- }
- } else if (p->cmd == EC_CHARGE_CONTROL_CMD_GET) {
- r->mode = get_chg_ctrl_mode();
- r->sustain_soc.lower = sustain_soc.lower;
- r->sustain_soc.upper = sustain_soc.upper;
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
- } else {
- return EC_RES_INVALID_PARAM;
- }
- }
-
- rv = set_chg_ctrl_mode(p->mode);
- if (rv != EC_SUCCESS)
- return EC_RES_ERROR;
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_CHARGE_CONTROL, charge_command_charge_control,
- EC_VER_MASK(1) | EC_VER_MASK(2));
-
-static void reset_current_limit(void)
-{
- user_current_limit = -1U;
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, reset_current_limit, HOOK_PRIO_DEFAULT);
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, reset_current_limit, HOOK_PRIO_DEFAULT);
-
-static enum ec_status
-charge_command_current_limit(struct host_cmd_handler_args *args)
-{
- const struct ec_params_current_limit *p = args->params;
-
- user_current_limit = p->limit;
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_CHARGE_CURRENT_LIMIT, charge_command_current_limit,
- EC_VER_MASK(0));
-
-/*
- * Expose charge/battery related state
- *
- * @param param command to get corresponding data
- * @param value the corresponding data
- * @return EC_SUCCESS or error
- */
-static int charge_get_charge_state_debug(int param, uint32_t *value)
-{
- switch (param) {
- case CS_PARAM_DEBUG_CTL_MODE:
- *value = get_chg_ctrl_mode();
- break;
- case CS_PARAM_DEBUG_MANUAL_CURRENT:
- *value = manual_current;
- break;
- case CS_PARAM_DEBUG_MANUAL_VOLTAGE:
- *value = manual_voltage;
- break;
- case CS_PARAM_DEBUG_SEEMS_DEAD:
- *value = battery_seems_dead;
- break;
- case CS_PARAM_DEBUG_SEEMS_DISCONNECTED:
- *value = battery_seems_disconnected;
- break;
- case CS_PARAM_DEBUG_BATT_REMOVED:
- *value = battery_was_removed;
- break;
- default:
- *value = 0;
- return EC_ERROR_INVAL;
- }
-
- return EC_SUCCESS;
-}
-
-static enum ec_status
-charge_command_charge_state(struct host_cmd_handler_args *args)
-{
- const struct ec_params_charge_state *in = args->params;
- struct ec_response_charge_state *out = args->response;
- uint32_t val;
- int rv = EC_RES_SUCCESS;
- int chgnum = 0;
-
- if (args->version > 0)
- chgnum = in->chgnum;
-
- switch (in->cmd) {
-
- case CHARGE_STATE_CMD_GET_STATE:
- out->get_state.ac = curr.ac;
- out->get_state.chg_voltage = curr.chg.voltage;
- out->get_state.chg_current = curr.chg.current;
- out->get_state.chg_input_current = curr.chg.input_current;
- out->get_state.batt_state_of_charge = curr.batt.state_of_charge;
- args->response_size = sizeof(out->get_state);
- break;
-
- case CHARGE_STATE_CMD_GET_PARAM:
- val = 0;
- if (IS_ENABLED(CONFIG_CHARGER_PROFILE_OVERRIDE)
- && in->get_param.param >= CS_PARAM_CUSTOM_PROFILE_MIN
- && in->get_param.param <= CS_PARAM_CUSTOM_PROFILE_MAX) {
- /* custom profile params */
- rv = charger_profile_override_get_param(
- in->get_param.param, &val);
- } else if (IS_ENABLED(CONFIG_CHARGE_STATE_DEBUG)
- && in->get_param.param >= CS_PARAM_DEBUG_MIN
- && in->get_param.param <= CS_PARAM_DEBUG_MAX) {
- /* debug params */
- rv = charge_get_charge_state_debug(
- in->get_param.param, &val);
- } else {
- /* standard params */
- switch (in->get_param.param) {
- case CS_PARAM_CHG_VOLTAGE:
- val = curr.chg.voltage;
- break;
- case CS_PARAM_CHG_CURRENT:
- val = curr.chg.current;
- break;
- case CS_PARAM_CHG_INPUT_CURRENT:
- val = curr.chg.input_current;
- break;
- case CS_PARAM_CHG_STATUS:
- val = curr.chg.status;
- break;
- case CS_PARAM_CHG_OPTION:
- val = curr.chg.option;
- break;
- case CS_PARAM_LIMIT_POWER:
-#ifdef CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW
- /*
- * LIMIT_POWER status is based on battery level
- * and external charger power.
- */
- if ((curr.batt.is_present != BP_YES ||
- curr.batt.state_of_charge <
- CONFIG_CHARGER_LIMIT_POWER_THRESH_BAT_PCT)
- && charge_manager_get_power_limit_uw() <
- CONFIG_CHARGER_LIMIT_POWER_THRESH_CHG_MW
- * 1000 && system_is_locked())
- val = 1;
- else
-#endif
- val = 0;
- break;
- default:
- rv = EC_RES_INVALID_PARAM;
- }
- }
-
- /* got something */
- out->get_param.value = val;
- args->response_size = sizeof(out->get_param);
- break;
-
- case CHARGE_STATE_CMD_SET_PARAM:
- if (system_is_locked())
- return EC_RES_ACCESS_DENIED;
-
- val = in->set_param.value;
- if (IS_ENABLED(CONFIG_CHARGER_PROFILE_OVERRIDE)
- && in->set_param.param >= CS_PARAM_CUSTOM_PROFILE_MIN
- && in->set_param.param <= CS_PARAM_CUSTOM_PROFILE_MAX) {
- /* custom profile params */
- rv = charger_profile_override_set_param(
- in->set_param.param, val);
- } else {
- switch (in->set_param.param) {
- case CS_PARAM_CHG_VOLTAGE:
- chgstate_set_manual_voltage(val);
- break;
- case CS_PARAM_CHG_CURRENT:
- chgstate_set_manual_current(val);
- break;
- case CS_PARAM_CHG_INPUT_CURRENT:
- if (charger_set_input_current_limit(chgnum,
- val))
- rv = EC_RES_ERROR;
- break;
- case CS_PARAM_CHG_STATUS:
- case CS_PARAM_LIMIT_POWER:
- /* Can't set this */
- rv = EC_RES_ACCESS_DENIED;
- break;
- case CS_PARAM_CHG_OPTION:
- if (charger_set_option(val))
- rv = EC_RES_ERROR;
- break;
- default:
- rv = EC_RES_INVALID_PARAM;
-
- }
- }
- break;
-
- default:
- CPRINTS("EC_CMD_CHARGE_STATE: bad cmd 0x%x", in->cmd);
- rv = EC_RES_INVALID_PARAM;
- }
-
- return rv;
-}
-
-DECLARE_HOST_COMMAND(EC_CMD_CHARGE_STATE, charge_command_charge_state,
- EC_VER_MASK(0) | EC_VER_MASK(1));
-
-/*****************************************************************************/
-/* Console commands */
-
-#ifdef CONFIG_CMD_PWR_AVG
-
-static int command_pwr_avg(int argc, char **argv)
-{
- int avg_mv;
- int avg_ma;
- int avg_mw;
-
- if (argc != 1)
- return EC_ERROR_PARAM_COUNT;
-
- avg_mv = battery_get_avg_voltage();
- if (avg_mv < 0)
- return EC_ERROR_UNKNOWN;
- avg_ma = battery_get_avg_current();
- avg_mw = avg_mv * avg_ma / 1000;
-
- ccprintf("mv = %d\nma = %d\nmw = %d\n",
- avg_mv, avg_ma, avg_mw);
- return EC_SUCCESS;
-}
-
-DECLARE_CONSOLE_COMMAND(pwr_avg, command_pwr_avg,
- NULL,
- "Get 1 min power average");
-
-#endif /* CONFIG_CMD_PWR_AVG */
-
-static int command_chgstate(int argc, char **argv)
-{
- int rv;
- int val;
- char *e;
-
- if (argc > 1) {
- if (!strcasecmp(argv[1], "idle")) {
- if (argc <= 2)
- return EC_ERROR_PARAM_COUNT;
- if (!parse_bool(argv[2], &val))
- return EC_ERROR_PARAM2;
- rv = set_chg_ctrl_mode(val ? CHARGE_CONTROL_IDLE :
- CHARGE_CONTROL_NORMAL);
- if (rv)
- return rv;
- } else if (!strcasecmp(argv[1], "discharge")) {
- if (argc <= 2)
- return EC_ERROR_PARAM_COUNT;
- if (!parse_bool(argv[2], &val))
- return EC_ERROR_PARAM2;
- rv = set_chg_ctrl_mode(val ? CHARGE_CONTROL_DISCHARGE :
- CHARGE_CONTROL_NORMAL);
- if (rv)
- return rv;
- } else if (!strcasecmp(argv[1], "debug")) {
- if (argc <= 2)
- return EC_ERROR_PARAM_COUNT;
- if (!parse_bool(argv[2], &debugging))
- return EC_ERROR_PARAM2;
- } else if (!strcasecmp(argv[1], "sustain")) {
- int lower, upper;
-
- if (argc <= 3)
- return EC_ERROR_PARAM_COUNT;
- lower = strtoi(argv[2], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2;
- upper = strtoi(argv[3], &e, 0);
- if (*e)
- return EC_ERROR_PARAM3;
- rv = battery_sustainer_set(lower, upper);
- if (rv)
- return EC_ERROR_INVAL;
- } else {
- return EC_ERROR_PARAM1;
- }
- }
-
- dump_charge_state();
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(chgstate, command_chgstate,
- "[idle|discharge|debug on|off]"
- "\n[sustain <lower> <upper>]",
- "Get/set charge state machine status");
-
-#ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT
-static int command_chgdualdebug(int argc, char **argv)
-{
- int val;
- char *e;
-
- if (argc > 1) {
- if (argv[1][0] == 'c') {
- if (argc <= 2)
- return EC_ERROR_PARAM_COUNT;
-
- if (!strcasecmp(argv[2], "auto")) {
- val = -1;
- } else {
- val = strtoi(argv[2], &e, 0);
- if (*e || val < 0)
- return EC_ERROR_PARAM2;
- }
-
- manual_ac_current_base = val;
- charge_wakeup();
- } else if (argv[1][0] == 'd') {
- if (argc <= 2)
- return EC_ERROR_PARAM_COUNT;
-
- if (!strcasecmp(argv[2], "auto")) {
- manual_noac_enabled = 0;
- } else {
- val = strtoi(argv[2], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2;
- manual_noac_current_base = val;
- manual_noac_enabled = 1;
- }
- charge_wakeup();
- } else {
- return EC_ERROR_PARAM1;
- }
- } else {
- ccprintf("Base/Lid: %d%s/%d mA\n",
- prev_current_base, prev_allow_charge_base ? "+" : "",
- prev_current_lid);
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(chgdualdebug, command_chgdualdebug,
- "[charge (auto|<current>)|discharge (auto|<current>)]",
- "Manually control dual-battery charging algorithm.");
-#endif
diff --git a/common/charger.c b/common/charger.c
deleted file mode 100644
index 764f8b7ba7..0000000000
--- a/common/charger.c
+++ /dev/null
@@ -1,712 +0,0 @@
-/* Copyright 2013 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.
- *
- * Common functions for battery charging.
- */
-
-#include "battery_smart.h"
-#include "charge_state_v2.h"
-#include "charger.h"
-#include "common.h"
-#include "console.h"
-#include "dptf.h"
-#include "host_command.h"
-#include "printf.h"
-#include "util.h"
-#include "hooks.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_CHARGER, outstr)
-#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args)
-
-/* DPTF current limit, -1 = none */
-static int dptf_limit_ma = -1;
-
-void dptf_set_charging_current_limit(int ma)
-{
- dptf_limit_ma = ma >= 0 ? ma : -1;
-}
-
-int dptf_get_charging_current_limit(void)
-{
- return dptf_limit_ma;
-}
-
-static void dptf_disable_hook(void)
-{
- /* Before get to Sx, EC should take control of charger from DPTF */
- dptf_limit_ma = -1;
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, dptf_disable_hook, HOOK_PRIO_DEFAULT);
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, dptf_disable_hook, HOOK_PRIO_DEFAULT);
-
-/*
- * Boards should override this function if their count may vary during run-time
- * due to different DB options.
- */
-__overridable uint8_t board_get_charger_chip_count(void)
-{
- return CHARGER_NUM;
-}
-
-int charger_closest_voltage(int voltage)
-{
- const struct charger_info *info = charger_get_info();
-
- /*
- * If the requested voltage is non-zero but below our minimum,
- * return the minimum. See crosbug.com/p/8662.
- */
- if (voltage > 0 && voltage < info->voltage_min)
- return info->voltage_min;
-
- /* Clip to max */
- if (voltage > info->voltage_max)
- return info->voltage_max;
-
- /* Otherwise round down to nearest voltage step */
- return voltage - (voltage % info->voltage_step);
-}
-
-int charger_closest_current(int current)
-{
- const struct charger_info * const info = charger_get_info();
-
- /* Apply DPTF limit if necessary */
- if (dptf_limit_ma >= 0 && current > dptf_limit_ma)
- current = dptf_limit_ma;
-
- /*
- * If the requested current is non-zero but below our minimum,
- * return the minimum. See crosbug.com/p/8662.
- */
- if (current > 0 && current < info->current_min)
- return info->current_min;
-
- /* Clip to max */
- if (current > info->current_max)
- return info->current_max;
-
- /* Otherwise round down to nearest current step */
- return current - (current % info->current_step);
-}
-
-void charger_get_params(struct charger_params *chg)
-{
- int chgnum = 0;
-
- if (IS_ENABLED(CONFIG_OCPC))
- chgnum = charge_get_active_chg_chip();
-
- memset(chg, 0, sizeof(*chg));
-
- /*
- * Only the primary charger(0) can tightly regulate the current,
- * therefore always query the primary charger.
- */
- if (charger_get_current(0, &chg->current))
- chg->flags |= CHG_FLAG_BAD_CURRENT;
-
- if (charger_get_voltage(chgnum, &chg->voltage))
- chg->flags |= CHG_FLAG_BAD_VOLTAGE;
-
- if (charger_get_input_current_limit(chgnum, &chg->input_current))
- chg->flags |= CHG_FLAG_BAD_INPUT_CURRENT;
-
- if (charger_get_status(&chg->status))
- chg->flags |= CHG_FLAG_BAD_STATUS;
-
- if (charger_get_option(&chg->option))
- chg->flags |= CHG_FLAG_BAD_OPTION;
-}
-
-static void print_item_name(const char *name)
-{
- ccprintf(" %-8s", name);
-}
-
-static int check_print_error(int rv)
-{
- if (rv == EC_SUCCESS)
- return 1;
- ccputs(rv == EC_ERROR_UNIMPLEMENTED ? "(unsupported)\n" : "(error)\n");
- return 0;
-}
-
-void print_charger_debug(int chgnum)
-{
- int d;
- const struct charger_info *info = charger_get_info();
-
- /* info */
- print_item_name("Name:");
- ccprintf("%s\n", info->name);
-
- /* option */
- print_item_name("Option:");
- if (check_print_error(charger_get_option(&d)))
- ccprintf("%pb (0x%04x)\n", BINARY_VALUE(d, 16), d);
-
- /* manufacturer id */
- print_item_name("Man id:");
- if (check_print_error(charger_manufacturer_id(&d)))
- ccprintf("0x%04x\n", d);
-
- /* device id */
- print_item_name("Dev id:");
- if (check_print_error(charger_device_id(&d)))
- ccprintf("0x%04x\n", d);
-
- /* charge voltage limit */
- print_item_name("V_batt:");
- if (check_print_error(charger_get_voltage(chgnum, &d)))
- ccprintf("%5d (%4d - %5d, %3d)\n", d, info->voltage_min,
- info->voltage_max, info->voltage_step);
-
- /* charge current limit */
- print_item_name("I_batt:");
- if (check_print_error(charger_get_current(chgnum, &d)))
- ccprintf("%5d (%4d - %5d, %3d)\n", d, info->current_min,
- info->current_max, info->current_step);
-
- /* input current limit */
- print_item_name("I_in:");
- if (check_print_error(charger_get_input_current_limit(chgnum, &d)))
- ccprintf("%5d (%4d - %5d, %3d)\n", d, info->input_current_min,
- info->input_current_max, info->input_current_step);
-
- /* dptf current limit */
- print_item_name("I_dptf:");
- if (dptf_limit_ma >= 0)
- ccprintf("%5d\n", dptf_limit_ma);
- else
- ccputs("disabled\n");
-}
-
-static int command_charger(int argc, char **argv)
-{
- int d;
- char *e;
- int idx_provided = 0;
- int chgnum;
-
- if (argc == 1) {
- print_charger_debug(0);
- return EC_SUCCESS;
- }
-
- idx_provided = isdigit((unsigned char)argv[1][0]);
- if (idx_provided)
- chgnum = atoi(argv[1]);
- else
- chgnum = 0;
-
- if ((argc == 2) && idx_provided) {
- print_charger_debug(chgnum);
- return EC_SUCCESS;
- }
-
- if (strcasecmp(argv[1+idx_provided], "input") == 0) {
- d = strtoi(argv[2+idx_provided], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2+idx_provided;
- return charger_set_input_current_limit(chgnum, d);
- } else if (strcasecmp(argv[1+idx_provided], "current") == 0) {
- d = strtoi(argv[2+idx_provided], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2+idx_provided;
- chgstate_set_manual_current(d);
- return charger_set_current(chgnum, d);
- } else if (strcasecmp(argv[1+idx_provided], "voltage") == 0) {
- d = strtoi(argv[2+idx_provided], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2+idx_provided;
- chgstate_set_manual_voltage(d);
- return charger_set_voltage(chgnum, d);
- } else if (strcasecmp(argv[1+idx_provided], "dptf") == 0) {
- d = strtoi(argv[2+idx_provided], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2+idx_provided;
- dptf_limit_ma = d;
- return EC_SUCCESS;
- } else {
- return EC_ERROR_PARAM1+idx_provided;
- }
-}
-
-DECLARE_CONSOLE_COMMAND(charger, command_charger,
- "[chgnum] [input | current | voltage | dptf] [newval]",
- "Get or set charger param(s)");
-
-/* Driver wrapper functions */
-
-static void charger_chips_init(void)
-{
- int chip;
-
- for (chip = 0; chip < board_get_charger_chip_count(); chip++) {
- if (chg_chips[chip].drv->init)
- chg_chips[chip].drv->init(chip);
- }
-}
-DECLARE_HOOK(HOOK_INIT, charger_chips_init, HOOK_PRIO_INIT_I2C + 1);
-
-enum ec_error_list charger_post_init(void)
-{
- int chgnum = 0;
-
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->post_init)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->post_init(chgnum);
-}
-
-const struct charger_info *charger_get_info(void)
-{
- int chgnum = 0;
-
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return NULL;
- }
-
- if (!chg_chips[chgnum].drv->get_info)
- return NULL;
-
- return chg_chips[chgnum].drv->get_info(chgnum);
-}
-
-enum ec_error_list charger_get_status(int *status)
-{
- int chgnum = 0;
-
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->get_status)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->get_status(chgnum, status);
-}
-
-enum ec_error_list charger_set_mode(int mode)
-{
- int chgnum = 0;
-
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->set_mode)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->set_mode(chgnum, mode);
-}
-
-enum ec_error_list charger_enable_otg_power(int chgnum, int enabled)
-{
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->enable_otg_power)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->enable_otg_power(chgnum, enabled);
-}
-
-enum ec_error_list charger_set_otg_current_voltage(int chgnum,
- int output_current,
- int output_voltage)
-{
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->set_otg_current_voltage)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->set_otg_current_voltage(
- chgnum, output_current, output_voltage);
-}
-
-int charger_is_sourcing_otg_power(int port)
-{
- int chgnum = 0;
-
- if (IS_ENABLED(CONFIG_OCPC))
- chgnum = port;
-
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return 0;
- }
-
- if (!chg_chips[chgnum].drv->is_sourcing_otg_power)
- return 0;
-
- return chg_chips[chgnum].drv->is_sourcing_otg_power(chgnum, port);
-}
-
-enum ec_error_list charger_get_actual_current(int chgnum, int *current)
-{
- /* Note: chgnum may be -1 if no active port is selected */
- if (chgnum < 0)
- return EC_ERROR_INVAL;
-
- if (chgnum >= board_get_charger_chip_count()) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->get_actual_current)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->get_actual_current(chgnum, current);
-}
-
-enum ec_error_list charger_get_current(int chgnum, int *current)
-{
- /* Note: chgnum may be -1 if no active port is selected */
- if (chgnum < 0)
- return EC_ERROR_INVAL;
-
- if (chgnum >= board_get_charger_chip_count()) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->get_current)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->get_current(chgnum, current);
-}
-
-enum ec_error_list charger_set_current(int chgnum, int current)
-{
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->set_current)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->set_current(chgnum, current);
-}
-
-enum ec_error_list charger_get_actual_voltage(int chgnum, int *voltage)
-{
- if (chgnum < 0)
- return EC_ERROR_INVAL;
-
- if (chgnum >= board_get_charger_chip_count()) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->get_actual_voltage)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->get_actual_voltage(chgnum, voltage);
-}
-
-enum ec_error_list charger_get_voltage(int chgnum, int *voltage)
-{
- if (chgnum < 0)
- return EC_ERROR_INVAL;
-
- if (chgnum >= board_get_charger_chip_count()) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->get_voltage)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->get_voltage(chgnum, voltage);
-}
-
-enum ec_error_list charger_set_voltage(int chgnum, int voltage)
-{
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->set_voltage)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->set_voltage(chgnum, voltage);
-}
-
-enum ec_error_list charger_discharge_on_ac(int enable)
-{
- int chgnum;
- int rv = EC_ERROR_UNIMPLEMENTED;
-
- if (IS_ENABLED(CONFIG_CHARGER_DISCHARGE_ON_AC_CUSTOM))
- return board_discharge_on_ac(enable);
-
- /*
- * When discharge on AC is selected, cycle through all chargers to
- * enable or disable this feature.
- */
- for (chgnum = 0; chgnum < board_get_charger_chip_count(); chgnum++) {
- if (chg_chips[chgnum].drv->discharge_on_ac)
- rv = chg_chips[chgnum].drv->discharge_on_ac(chgnum,
- enable);
- }
-
- return rv;
-}
-
-enum ec_error_list charger_get_vbus_voltage(int port, int *voltage)
-{
- int chgnum = 0;
-
- /* Note: Assumes USBPD port == chgnum on multi-charger systems */
- if (!IS_ENABLED(CONFIG_CHARGER_SINGLE_CHIP))
- chgnum = port;
-
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return 0;
- }
-
- if (!chg_chips[chgnum].drv->get_vbus_voltage)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->get_vbus_voltage(chgnum, port, voltage);
-}
-
-enum ec_error_list charger_set_input_current_limit(int chgnum,
- int input_current)
-{
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->set_input_current_limit)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->set_input_current_limit(chgnum,
- input_current);
-}
-
-enum ec_error_list charger_get_input_current_limit(int chgnum,
- int *input_current)
-{
- /* Note: may be called with CHARGE_PORT_NONE regularly */
- if (chgnum < 0)
- return EC_ERROR_INVAL;
-
- if (chgnum >= board_get_charger_chip_count()) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->get_input_current_limit)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->get_input_current_limit(chgnum,
- input_current);
-}
-
-enum ec_error_list charger_get_input_current(int chgnum, int *input_current)
-{
- if (chgnum < 0)
- return EC_ERROR_INVAL;
-
- if (chgnum >= board_get_charger_chip_count()) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->get_input_current)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->get_input_current(chgnum, input_current);
-}
-
-enum ec_error_list charger_manufacturer_id(int *id)
-{
- int chgnum = 0;
-
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->manufacturer_id)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->manufacturer_id(chgnum, id);
-}
-
-enum ec_error_list charger_device_id(int *id)
-{
- int chgnum = 0;
-
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->device_id)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->device_id(chgnum, id);
-}
-
-enum ec_error_list charger_get_option(int *option)
-{
- int chgnum = 0;
-
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->get_option)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->get_option(chgnum, option);
-}
-
-enum ec_error_list charger_set_option(int option)
-{
- int chgnum = 0;
-
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->set_option)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->set_option(chgnum, option);
-}
-
-enum ec_error_list charger_set_hw_ramp(int enable)
-{
- int chgnum = 0;
-
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (!chg_chips[chgnum].drv->set_hw_ramp)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->set_hw_ramp(chgnum, enable);
-}
-
-#ifdef CONFIG_CHARGE_RAMP_HW
-int chg_ramp_is_stable(void)
-{
- int chgnum = 0;
-
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return 0;
- }
-
- if (!chg_chips[chgnum].drv->ramp_is_stable)
- return 0;
-
- return chg_chips[chgnum].drv->ramp_is_stable(chgnum);
-}
-
-int chg_ramp_is_detected(void)
-{
- int chgnum = 0;
-
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return 0;
- }
-
- if (!chg_chips[chgnum].drv->ramp_is_detected)
- return 0;
-
- return chg_chips[chgnum].drv->ramp_is_detected(chgnum);
-}
-
-int chg_ramp_get_current_limit(void)
-{
- int chgnum = 0;
-
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return 0;
- }
-
- if (!chg_chips[chgnum].drv->ramp_get_current_limit)
- return 0;
-
- return chg_chips[chgnum].drv->ramp_get_current_limit(chgnum);
-}
-#endif
-
-enum ec_error_list charger_set_vsys_compensation(int chgnum,
- struct ocpc_data *ocpc,
- int current_ma,
- int voltage_mv)
-{
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- /*
- * This shouldn't happen as this should only be called on chargers
- * that support this.
- */
- if (!chg_chips[chgnum].drv->set_vsys_compensation)
- return EC_ERROR_UNIMPLEMENTED;
-
- return chg_chips[chgnum].drv->set_vsys_compensation(
- chgnum, ocpc, current_ma, voltage_mv);
-}
-
-enum ec_error_list charger_is_icl_reached(int chgnum, bool *reached)
-{
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (chg_chips[chgnum].drv->is_icl_reached)
- return chg_chips[chgnum].drv->is_icl_reached(chgnum, reached);
-
- return EC_ERROR_UNIMPLEMENTED;
-}
-
-enum ec_error_list charger_enable_linear_charge(int chgnum, bool enable)
-{
- if ((chgnum < 0) || (chgnum >= board_get_charger_chip_count())) {
- CPRINTS("%s(%d) Invalid charger!", __func__, chgnum);
- return EC_ERROR_INVAL;
- }
-
- if (chg_chips[chgnum].drv->enable_linear_charge)
- return chg_chips[chgnum].drv->enable_linear_charge(chgnum,
- enable);
-
- return EC_ERROR_UNIMPLEMENTED;
-}
diff --git a/common/charger_profile_override.c b/common/charger_profile_override.c
deleted file mode 100644
index 2b691b9a5a..0000000000
--- a/common/charger_profile_override.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/* Copyright 2016 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.
- *
- * Charger profile override for fast charging
- */
-
-#include "charger_profile_override.h"
-#include "console.h"
-#include "ec_commands.h"
-#include "util.h"
-
-#ifdef CONFIG_CMD_CHARGER_PROFILE_OVERRIDE_TEST
-static int fast_charge_test_on;
-static int test_flag_temp;
-static int test_flag_vtg;
-static int test_temp_c;
-static int test_vtg_mV = -1;
-#endif
-
-static int fast_charging_allowed = 1;
-
-int charger_profile_override_common(struct charge_state_data *curr,
- const struct fast_charge_params *fast_chg_params,
- const struct fast_charge_profile **prev_chg_prof_info,
- int batt_vtg_max)
-{
- int i, voltage_range;
- /* temp in 0.1 deg C */
- int temp_c = curr->batt.temperature - 2731;
- int temp_ranges = fast_chg_params->total_temp_ranges;
- const struct fast_charge_profile *chg_profile_info =
- fast_chg_params->chg_profile_info;
-
-#ifdef CONFIG_CMD_CHARGER_PROFILE_OVERRIDE_TEST
- if (fast_charge_test_on && test_vtg_mV != -1) {
- temp_c = TEMPC_TENTHS_OF_DEG(test_temp_c);
- curr->batt.voltage = test_vtg_mV;
-
- if (test_flag_temp)
- curr->batt.flags |= BATT_FLAG_BAD_TEMPERATURE;
- else
- curr->batt.flags &= BATT_FLAG_BAD_TEMPERATURE;
-
- if (test_flag_vtg)
- curr->batt.flags |= BATT_FLAG_BAD_VOLTAGE;
- else
- curr->batt.flags &= BATT_FLAG_BAD_VOLTAGE;
- }
-#endif
-
- /*
- * Determine temperature range.
- * If temp reading was bad, use last range.
- */
- if (!(curr->batt.flags & BATT_FLAG_BAD_TEMPERATURE)) {
- while (chg_profile_info && temp_ranges) {
- if (temp_c <= chg_profile_info->temp_c) {
- *prev_chg_prof_info = chg_profile_info;
- break;
- }
- chg_profile_info++;
- temp_ranges--;
- }
-
- /* Invalid charge profile selected */
- if (!chg_profile_info || !temp_ranges)
- return -1;
- }
-
- /*
- * If the battery voltage reading is bad or the battery voltage is
- * greater than or equal to the lower limit or the battery voltage is
- * not in the charger profile voltage range, consider battery has high
- * voltage range so that we charge at lower current limit.
- */
- voltage_range = CONFIG_CHARGER_PROFILE_VOLTAGE_RANGES - 1;
-
- if (!(curr->batt.flags & BATT_FLAG_BAD_VOLTAGE)) {
- for (i = 0; i < CONFIG_CHARGER_PROFILE_VOLTAGE_RANGES - 1;
- i++) {
- if (curr->batt.voltage <
- fast_chg_params->voltage_mV[i]) {
- voltage_range = i;
- break;
- }
- }
- }
-
- /*
- * If we are not charging or we aren't using fast charging profiles,
- * then do not override desired current and voltage.
- */
- if (curr->state != ST_CHARGE || !fast_charging_allowed)
- return 0;
-
- /*
- * Okay, impose our custom will:
- */
- curr->requested_current =
- (*prev_chg_prof_info)->current_mA[voltage_range];
- curr->requested_voltage = curr->requested_current ? batt_vtg_max : 0;
-
-#ifdef CONFIG_CMD_CHARGER_PROFILE_OVERRIDE_TEST
- if (fast_charge_test_on)
- ccprintf("Fast charge profile i=%dmA, v=%dmV\n",
- curr->requested_current, curr->requested_voltage);
-#endif
-
- return 0;
-}
-
-/* Customs options controllable by host command. */
-#define PARAM_FASTCHARGE (CS_PARAM_CUSTOM_PROFILE_MIN + 0)
-
-enum ec_status charger_profile_override_get_param(uint32_t param,
- uint32_t *value)
-{
- if (param == PARAM_FASTCHARGE) {
- *value = fast_charging_allowed;
- return EC_RES_SUCCESS;
- }
- return EC_RES_INVALID_PARAM;
-}
-
-enum ec_status charger_profile_override_set_param(uint32_t param,
- uint32_t value)
-{
- if (param == PARAM_FASTCHARGE) {
- fast_charging_allowed = value;
- return EC_RES_SUCCESS;
- }
- return EC_RES_INVALID_PARAM;
-}
-
-#ifdef CONFIG_CMD_CHARGER_PROFILE_OVERRIDE
-static int command_fastcharge(int argc, char **argv)
-{
- if (argc > 1 && !parse_bool(argv[1], &fast_charging_allowed))
- return EC_ERROR_PARAM1;
-
- ccprintf("fastcharge %s\n", fast_charging_allowed ? "on" : "off");
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(fastcharge, command_fastcharge,
- "[on|off]",
- "Get or set fast charging profile");
-#endif
-
-/*
- * Manipulate the temperature and voltage values and check if the correct
- * fast charging profile is selected.
- */
-#ifdef CONFIG_CMD_CHARGER_PROFILE_OVERRIDE_TEST
-static int command_fastcharge_test(int argc, char **argv)
-{
- char *e;
- int test_on;
-
- if (argc > 1 && !parse_bool(argv[1], &test_on))
- return EC_ERROR_PARAM2;
-
- /* Check if only tuurn printf message on / off */
- if (argc == 2) {
- fast_charge_test_on = test_on;
- test_vtg_mV = -1;
-
- return EC_SUCCESS;
- }
-
- /* Validate the input parameters */
- if ((test_on && argc != 6) || !test_on)
- return EC_ERROR_PARAM_COUNT;
-
- test_flag_temp = strtoi(argv[2], &e, 0);
- if (*e || test_flag_temp > 1 || test_flag_temp < 0)
- return EC_ERROR_PARAM3;
-
- test_flag_vtg = strtoi(argv[3], &e, 0);
- if (*e || test_flag_vtg > 1 || test_flag_vtg < 0)
- return EC_ERROR_PARAM4;
-
- test_temp_c = strtoi(argv[4], &e, 0);
- if (*e)
- return EC_ERROR_PARAM5;
-
- test_vtg_mV = strtoi(argv[5], &e, 0);
- if (*e || test_vtg_mV < 0) {
- test_vtg_mV = -1;
- return EC_ERROR_PARAM6;
- }
-
- fast_charge_test_on = 1;
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(fastchgtest, command_fastcharge_test,
- "off | on tempflag[1|0] vtgflag[1|0] temp_c vtg_mV",
- "Check if fastcharge profile works");
-#endif
diff --git a/common/clz.c b/common/clz.c
deleted file mode 100644
index b0b58e76a0..0000000000
--- a/common/clz.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Copyright 2014 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.
- *
- * Software emulation for CLZ instruction
- */
-
-#include "common.h"
-
-/**
- * Count leading zeros
- *
- * @param x non null integer.
- * @return the number of leading 0-bits in x,
- * starting at the most significant bit position.
- */
-int __keep __clzsi2(int x)
-{
- int r = 0;
-
- if (!x)
- return 32;
- if (!(x & 0xffff0000u)) {
- x <<= 16;
- r += 16;
- }
- if (!(x & 0xff000000u)) {
- x <<= 8;
- r += 8;
- }
- if (!(x & 0xf0000000u)) {
- x <<= 4;
- r += 4;
- }
- if (!(x & 0xc0000000u)) {
- x <<= 2;
- r += 2;
- }
- if (!(x & 0x80000000u)) {
- x <<= 1;
- r += 1;
- }
- return r;
-}
diff --git a/common/crc.c b/common/crc.c
deleted file mode 100644
index 8b45150b67..0000000000
--- a/common/crc.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/* Copyright 2014 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.
- */
-/* CRC-32 implementation with USB constants */
-
-#include "common.h"
-
-/* Constants matching USB3 and USB PD definitions */
-#define CRC32_INITIAL 0xFFFFFFFF
-
-/* Pre-computed values for polynom 0x04C11DB7 */
-static const uint32_t crc32_tab[] = {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
- 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
- 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
- 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
- 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
- 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
- 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
- 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
- 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
- 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
- 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
- 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
- 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
- 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
- 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
- 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
- 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
- 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
- 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
- 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
- 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
- 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
-};
-
-static uint32_t _crc32_hash(uint32_t crc, const void *buf, int size)
-{
- const uint8_t *p;
-
- p = (const uint8_t *)buf;
-
- while (size--) {
- crc ^= *p++;
- crc = crc32_tab[crc & 0xFF] ^ (crc >> 8);
- }
-
- return crc;
-}
-
-void crc32_ctx_init(uint32_t *crc)
-{
- *crc = CRC32_INITIAL;
-}
-
-void crc32_ctx_hash(uint32_t *crc, const void *buf, int size)
-{
- *crc = _crc32_hash(*crc, buf, size);
-}
-
-void crc32_ctx_hash32(uint32_t *crc, uint32_t val)
-{
- *crc = _crc32_hash(*crc, &val, sizeof(val));
-}
-
-void crc32_ctx_hash16(uint32_t *crc, uint16_t val)
-{
- *crc = _crc32_hash(*crc, &val, sizeof(val));
-}
-
-void crc32_ctx_hash8(uint32_t *crc, uint8_t val)
-{
- *crc = _crc32_hash(*crc, &val, sizeof(val));
-}
-
-uint32_t crc32_ctx_result(uint32_t *crc)
-{
- return *crc ^ 0xFFFFFFFF;
-}
-
-/* Accumulator for the CRC */
-static uint32_t crc_;
-
-void crc32_init(void)
-{
- crc32_ctx_init(&crc_);
-}
-
-void crc32_hash(const void *buf, int size)
-{
- crc32_ctx_hash(&crc_, buf, size);
-}
-
-void crc32_hash32(uint32_t val)
-{
- crc32_ctx_hash32(&crc_, val);
-}
-
-void crc32_hash16(uint16_t val)
-{
- crc32_ctx_hash16(&crc_, val);
-}
-
-uint32_t crc32_result(void)
-{
- return crc32_ctx_result(&crc_);
-}
diff --git a/common/crc8.c b/common/crc8.c
deleted file mode 100644
index 8098fa74eb..0000000000
--- a/common/crc8.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Copyright 2014 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.
- */
-#include "common.h"
-#include "crc8.h"
-
-inline uint8_t cros_crc8(const uint8_t *data, int len)
-{
- return cros_crc8_arg(data, len, 0);
-}
-
-uint8_t cros_crc8_arg(const uint8_t *data, int len, uint8_t previous_crc)
-{
- unsigned crc = previous_crc << 8;
- int i, j;
-
- for (j = len; j; j--, data++) {
- crc ^= (*data << 8);
- for (i = 8; i; i--) {
- if (crc & 0x8000)
- crc ^= (0x1070 << 3);
- crc <<= 1;
- }
- }
-
- return (uint8_t)(crc >> 8);
-}
diff --git a/common/ctz.c b/common/ctz.c
deleted file mode 100644
index bb6f69624e..0000000000
--- a/common/ctz.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Copyright 2017 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.
- *
- * Software emulation for CTZ instruction
- */
-
-#include "common.h"
-
-/**
- * Count trailing zeros
- *
- * @param x non null integer.
- * @return the number of trailing 0-bits in x,
- * starting at the least significant bit position.
- *
- * Using a de Brujin sequence, as documented here:
- * http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup
- */
-int __keep __ctzsi2(int x)
-{
- static const uint8_t MulDeBruijnBitPos[32] = {
- 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
- 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
- };
- return MulDeBruijnBitPos[((uint32_t)((x & -x) * 0x077CB531U)) >> 27];
-}
diff --git a/common/curve25519-generic.c b/common/curve25519-generic.c
deleted file mode 120000
index 3218a877a2..0000000000
--- a/common/curve25519-generic.c
+++ /dev/null
@@ -1 +0,0 @@
-../third_party/boringssl/common/curve25519-generic.c \ No newline at end of file
diff --git a/common/curve25519.c b/common/curve25519.c
deleted file mode 120000
index aa9bebe86e..0000000000
--- a/common/curve25519.c
+++ /dev/null
@@ -1 +0,0 @@
-../third_party/boringssl/common/curve25519.c \ No newline at end of file
diff --git a/common/device_event.c b/common/device_event.c
deleted file mode 100644
index f7944ae930..0000000000
--- a/common/device_event.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/* Copyright 2017 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.
- */
-
-/* Device event commands for Chrome EC */
-
-#include "atomic.h"
-#include "common.h"
-#include "console.h"
-#include "host_command.h"
-#include "lpc.h"
-#include "mkbp_event.h"
-#include "util.h"
-
-/* Console output macros */
-#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;
-
-uint32_t device_get_current_events(void)
-{
- return device_current_events;
-}
-
-static uint32_t device_get_and_clear_events(void)
-{
- return atomic_clear(&device_current_events);
-}
-
-static uint32_t device_get_enabled_events(void)
-{
- return device_enabled_events;
-}
-
-void device_set_events(uint32_t mask)
-{
- /* Ignore events that are not enabled */
- mask &= device_enabled_events;
-
- if ((device_current_events & mask) != mask) {
- CPRINTS("device event set 0x%08x", mask);
- } else {
- /*
- * We are here because there is no flag change (1->1, 0->0).
- * For 0->0, we shouldn't notify the host because the flag is
- * disabled. For 1->1, it's most likely redundant but we still
- * need to notify the host in case the host didn't have a
- * chance to read the flags. Otherwise, the flag would never be
- * consumed because the host would never be notified.
- */
- if (!mask)
- return;
- }
-
- atomic_or(&device_current_events, mask);
-
- /* Signal host that a device event is pending */
- host_set_single_event(EC_HOST_EVENT_DEVICE);
-}
-
-void device_clear_events(uint32_t mask)
-{
- /* Only print if something's about to change */
- if (device_current_events & mask)
- CPRINTS("device event clear 0x%08x", mask);
-
- atomic_clear_bits(&device_current_events, mask);
-}
-
-static void device_set_enabled_events(uint32_t mask)
-{
- if ((device_enabled_events & mask) != mask)
- CPRINTS("device enabled events set 0x%08x", mask);
-
- device_enabled_events = mask;
-}
-
-void device_enable_event(enum ec_device_event event)
-{
- atomic_or(&device_enabled_events, EC_DEVICE_EVENT_MASK(event));
-}
-
-/*****************************************************************************/
-/* Console commands */
-
-#ifdef CONFIG_CMD_DEVICE_EVENT
-static int command_device_event(int argc, char **argv)
-{
- /* Handle sub-commands */
- if (argc == 3) {
- char *e;
- int i = strtoi(argv[2], &e, 0);
-
- if (*e)
- return EC_ERROR_PARAM2;
- else if (!strcasecmp(argv[1], "set"))
- device_set_events(i);
- else if (!strcasecmp(argv[1], "clear"))
- device_clear_events(i);
- else if (!strcasecmp(argv[1], "enable"))
- device_set_enabled_events(i);
- else
- return EC_ERROR_PARAM1;
- }
-
- ccprintf("Enabled Events: 0x%08x\n", device_get_enabled_events());
- ccprintf("Current Events: 0x%08x\n", device_get_current_events());
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(deviceevent, command_device_event,
- "[set | clear | enable] [mask]",
- "Print / set device event state");
-#endif
-
-/*****************************************************************************/
-/* Host commands */
-
-static enum ec_status device_event_cmd(struct host_cmd_handler_args *args)
-{
- const struct ec_params_device_event *p = args->params;
- struct ec_response_device_event *r = args->response;
-
- switch (p->param) {
- case EC_DEVICE_EVENT_PARAM_GET_CURRENT_EVENTS:
- r->event_mask = device_get_and_clear_events();
- break;
- case EC_DEVICE_EVENT_PARAM_GET_ENABLED_EVENTS:
- r->event_mask = device_get_enabled_events();
- break;
- case EC_DEVICE_EVENT_PARAM_SET_ENABLED_EVENTS:
- device_set_enabled_events(p->event_mask);
- r->event_mask = device_get_enabled_events();
- break;
- default:
- return EC_RES_INVALID_PARAM;
- }
-
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_DEVICE_EVENT, device_event_cmd, EC_VER_MASK(0));
diff --git a/common/device_state.c b/common/device_state.c
deleted file mode 100644
index 0ba94d6115..0000000000
--- a/common/device_state.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/* Copyright 2016 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.
- */
-
-#include "console.h"
-#include "device_state.h"
-#include "hooks.h"
-
-#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args)
-
-/**
- * Return text description for a state
- *
- * @param state State
- * @return String describing that state
- */
-static const char *state_desc(enum device_state state)
-{
- return state == DEVICE_STATE_ON ? "on" :
- state == DEVICE_STATE_OFF ? "off" : "unknown";
-}
-
-enum device_state device_get_state(enum device_type device)
-{
- return device_states[device].state;
-}
-
-int device_set_state(enum device_type device, enum device_state state)
-{
- struct device_config *dc = device_states + device;
-
- /*
- * It'd be handy for debugging if we could print to the console when
- * device_set_state() is called. But unfortunately, it'll be called a
- * LOT when debouncing UART activity on DETECT_EC or DETECT_AP. So
- * only print when the last known state changes below.
- */
-
- dc->state = state;
-
- if (state != DEVICE_STATE_UNKNOWN && dc->last_known_state != state) {
- dc->last_known_state = state;
- CPRINTS("DEV %s -> %s", dc->name, state_desc(state));
- return 1;
- }
-
- return 0;
-}
-
-/**
- * Periodic check of device states.
- *
- * The board does all the work.
- *
- * Note that device states can change outside of this context as well, for
- * example, from a GPIO interrupt handler.
- */
-static void check_device_state(void)
-{
- int i;
-
- for (i = 0; i < DEVICE_COUNT; i++)
- board_update_device_state(i);
-}
-DECLARE_HOOK(HOOK_SECOND, check_device_state, HOOK_PRIO_DEFAULT);
-
-static int command_devices(int argc, char **argv)
-{
- const struct device_config *dc = device_states;
- int i;
-
- ccprintf("Device State LastKnown\n");
-
- for (i = 0; i < DEVICE_COUNT; i++, dc++)
- ccprintf("%-9s %-7s %s\n", dc->name, state_desc(dc->state),
- state_desc(dc->last_known_state));
-
- return EC_SUCCESS;
-}
-DECLARE_SAFE_CONSOLE_COMMAND(devices, command_devices,
- "",
- "Get the device states");
diff --git a/common/dps.c b/common/dps.c
deleted file mode 100644
index 235f4d4e08..0000000000
--- a/common/dps.c
+++ /dev/null
@@ -1,639 +0,0 @@
-/* Copyright 2021 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.
- *
- * Dynamic PDO Selection.
- */
-
-#include <stdint.h>
-
-#include "adc.h"
-#include "dps.h"
-#include "atomic.h"
-#include "battery.h"
-#include "console.h"
-#include "charger.h"
-#include "charge_manager.h"
-#include "charge_state.h"
-#include "charge_state_v2.h"
-#include "math_util.h"
-#include "task.h"
-#include "timer.h"
-#include "usb_common.h"
-#include "usb_pd.h"
-#include "util.h"
-#include "usb_pe_sm.h"
-
-
-#define K_MORE_PWR 96
-#define K_LESS_PWR 93
-#define K_SAMPLE 1
-#define K_WINDOW 3
-#define T_REQUEST_STABLE_TIME (10 * SECOND)
-#define T_NEXT_CHECK_TIME (5 * SECOND)
-
-#define DPS_FLAG_DISABLED BIT(0)
-#define DPS_FLAG_NO_SRCCAP BIT(1)
-#define DPS_FLAG_WAITING BIT(2)
-#define DPS_FLAG_SAMPLED BIT(3)
-#define DPS_FLAG_NEED_MORE_PWR BIT(4)
-
-#define DPS_FLAG_STOP_EVENTS (DPS_FLAG_DISABLED | \
- DPS_FLAG_NO_SRCCAP)
-#define DPS_FLAG_ALL GENMASK(31, 0)
-
-#define MAX_MOVING_AVG_WINDOW 5
-
-BUILD_ASSERT(K_MORE_PWR > K_LESS_PWR && 100 >= K_MORE_PWR && 100 >= K_LESS_PWR);
-
-/* lock for updating timeout value */
-static mutex_t dps_lock;
-static timestamp_t timeout;
-static bool is_enabled = true;
-static int debug_level;
-static bool fake_enabled;
-static int fake_mv, fake_ma;
-static int dynamic_mv;
-static int dps_port = CHARGE_PORT_NONE;
-static uint32_t flag;
-
-#define CPRINTF(format, args...) cprintf(CC_USBPD, "DPS " format, ##args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, "DPS " format, ##args)
-
-__overridable struct dps_config_t dps_config = {
- .k_less_pwr = K_LESS_PWR,
- .k_more_pwr = K_MORE_PWR,
- .k_sample = K_SAMPLE,
- .k_window = K_WINDOW,
- .t_stable = T_REQUEST_STABLE_TIME,
- .t_check = T_NEXT_CHECK_TIME,
- .is_more_efficient = NULL,
-};
-
-int dps_get_dynamic_voltage(void)
-{
- return dynamic_mv;
-}
-
-int dps_get_charge_port(void)
-{
- return dps_port;
-}
-
-bool dps_is_enabled(void)
-{
- return is_enabled;
-}
-
-static void dps_enable(bool en)
-{
- bool prev_en = is_enabled;
-
- is_enabled = en;
-
- if (is_enabled && !prev_en)
- task_wake(TASK_ID_DPS);
-}
-
-static void update_timeout(int us)
-{
- timestamp_t new_timeout;
-
- new_timeout.val = get_time().val + us;
-
- mutex_lock(&dps_lock);
- if (new_timeout.val > timeout.val)
- timeout = new_timeout;
- mutex_unlock(&dps_lock);
-}
-
-/*
- * DPS reset.
- */
-static void dps_reset(void)
-{
- dynamic_mv = PD_MAX_VOLTAGE_MV;
- dps_port = CHARGE_PORT_NONE;
-}
-
-/*
- * DPS initialization.
- */
-static void dps_init(void)
-{
- dps_reset();
-
- if (dps_config.k_window > MAX_MOVING_AVG_WINDOW) {
- dps_config.k_window = MAX_MOVING_AVG_WINDOW;
- CPRINTS("ERR:WIN");
- }
-
- if (dps_config.k_less_pwr > 100 ||
- dps_config.k_more_pwr > 100 ||
- dps_config.k_more_pwr <= dps_config.k_less_pwr) {
- dps_config.k_less_pwr = K_LESS_PWR;
- dps_config.k_more_pwr = K_MORE_PWR;
- CPRINTS("ERR:COEF");
- }
-}
-
-static bool is_near_limit(int val, int limit)
-{
- return val >= (limit * dps_config.k_more_pwr / 100);
-}
-
-bool is_more_efficient(int curr_mv, int prev_mv, int batt_mv, int batt_mw,
- int input_mw)
-{
- if (dps_config.is_more_efficient)
- return dps_config.is_more_efficient(curr_mv, prev_mv, batt_mv,
- batt_mw, input_mw);
-
- return ABS(curr_mv - batt_mv) < ABS(prev_mv - batt_mv);
-}
-
-/*
- * Get the input power of the active port.
- *
- * input_power = vbus * input_current
- *
- * @param vbus: VBUS in mV
- * @param input_curr: input current in mA
- *
- * @return input_power of the result of vbus * input_curr in mW
- */
-static int get_desired_input_power(int *vbus, int *input_current)
-{
- int active_port;
- int charger_id;
- enum ec_error_list rv;
-
- active_port = charge_manager_get_active_charge_port();
-
- if (active_port == CHARGE_PORT_NONE)
- return 0;
-
- charger_id = charge_get_active_chg_chip();
-
- if (fake_enabled) {
- *vbus = fake_mv;
- *input_current = fake_ma;
- return fake_mv * fake_ma / 1000;
- }
-
- rv = charger_get_input_current(charger_id, input_current);
- if (rv)
- return 0;
-
- *vbus = charge_manager_get_vbus_voltage(active_port);
-
- return (*vbus) * (*input_current) / 1000;
-}
-
-/*
- * Get the most efficient PDO voltage for the battery of the charging port
- *
- * | W\Batt | 1S(3.7V) | 2S(7.4V) | 3S(11.1V) | 4S(14.8V) |
- * --------------------------------------------------------
- * | 0-15W | 5V | 9V | 12V | 15V |
- * | 15-27W | 9V | 9V | 12V | 15V |
- * | 27-36W | 12V | 12V | 12V | 15V |
- * | 36-45W | 15V | 15V | 15V | 15V |
- * | 45-60W | 20V | 20V | 20V | 20V |
- *
- *
- * @return 0 if error occurs, else battery efficient voltage in mV
- */
-int get_efficient_voltage(void)
-{
- int eff_mv = 0;
- int batt_mv;
- int batt_pwr;
- int input_pwr, vbus, input_curr;
- const struct batt_params *batt = charger_current_battery_params();
-
- input_pwr = get_desired_input_power(&vbus, &input_curr);
-
- if (!input_pwr)
- return 0;
-
- if (battery_design_voltage(&batt_mv))
- return 0;
-
- batt_pwr = batt->current * batt->voltage / 1000;
-
- for (int i = 0; i < board_get_usb_pd_port_count(); ++i) {
- const int cnt = pd_get_src_cap_cnt(i);
- const uint32_t *src_caps = pd_get_src_caps(i);
-
- for (int j = 0; j < cnt; ++j) {
- int ma, mv, unused;
-
- pd_extract_pdo_power(src_caps[j], &ma, &mv, &unused);
- /*
- * If the eff_mv is not picked, or we have more
- * efficient voltage (less voltage diff)
- */
- if (eff_mv == 0 ||
- is_more_efficient(mv, eff_mv, batt_mv, batt_pwr,
- input_pwr))
- eff_mv = mv;
- }
- }
-
- return eff_mv;
-}
-
-struct pdo_candidate {
- int port;
- int mv;
- int mw;
-};
-
-#define UPDATE_CANDIDATE(new_port, new_mv, new_mw) \
- do { \
- cand->port = new_port; \
- cand->mv = new_mv; \
- cand->mw = new_mw; \
- } while (0)
-
-#define CLEAR_AND_RETURN() \
- do { \
- moving_avg_count = 0; \
- return false; \
- } while (0)
-
-/*
- * Evaluate the system power if a new PD power request is needed.
- *
- * @param struct pdo_candidate: The candidate PDO. (Return value)
- * @return true if a new power request, or false otherwise.
- */
-static bool has_new_power_request(struct pdo_candidate *cand)
-{
- int vbus, input_curr, input_pwr;
- int input_pwr_avg = 0, input_curr_avg = 0;
- int batt_pwr, batt_mv;
- int max_mv = pd_get_max_voltage();
- int req_pwr, req_ma, req_mv;
- int input_curr_limit;
- int active_port = charge_manager_get_active_charge_port();
- int charger_id;
- static int input_pwrs[MAX_MOVING_AVG_WINDOW];
- static int input_currs[MAX_MOVING_AVG_WINDOW];
- static int prev_active_port = CHARGE_PORT_NONE;
- static int prev_req_mv;
- static int moving_avg_count;
- const struct batt_params *batt = charger_current_battery_params();
-
- /* set a default value in case it early returns. */
- UPDATE_CANDIDATE(CHARGE_PORT_NONE, INT32_MAX, 0);
-
- if (active_port == CHARGE_PORT_NONE)
- CLEAR_AND_RETURN();
-
- req_mv = pd_get_requested_voltage(active_port);
- req_ma = pd_get_requested_current(active_port);
-
- if (!req_mv)
- CLEAR_AND_RETURN();
-
- if (battery_design_voltage(&batt_mv))
- CLEAR_AND_RETURN();
-
- /* if last sample is not the same as the current one, reset counting. */
- if (prev_req_mv != req_mv || prev_active_port != active_port)
- moving_avg_count = 0;
- prev_active_port = active_port;
- prev_req_mv = req_mv;
-
- req_pwr = req_mv * req_ma / 1000;
- batt_pwr = batt->current * batt->voltage / 1000;
- input_pwr = get_desired_input_power(&vbus, &input_curr);
-
- if (!input_pwr)
- CLEAR_AND_RETURN();
-
- /* record moving average */
- input_pwrs[moving_avg_count % dps_config.k_window] = input_pwr;
- input_currs[moving_avg_count % dps_config.k_window] = input_curr;
- if (++moving_avg_count < dps_config.k_window)
- return false;
-
- for (int i = 0; i < dps_config.k_window; i++) {
- input_curr_avg += input_currs[i];
- input_pwr_avg += input_pwrs[i];
- }
- input_curr_avg /= dps_config.k_window;
- input_pwr_avg /= dps_config.k_window;
-
- charger_id = charge_get_active_chg_chip();
-
- if (!charger_get_input_current_limit(charger_id, &input_curr_limit))
- /* set as last requested mA if we're unable to get the limit. */
- input_curr_limit = req_ma;
-
- /*
- * input power might be insufficient, force it to negotiate a more
- * powerful PDO.
- */
- if (is_near_limit(input_pwr_avg, req_pwr) ||
- is_near_limit(input_curr_avg, MIN(req_ma, input_curr_limit))) {
- flag |= DPS_FLAG_NEED_MORE_PWR;
- if (!fake_enabled)
- input_pwr_avg = req_pwr + 1;
- } else {
- flag &= ~DPS_FLAG_NEED_MORE_PWR;
- }
-
- if (debug_level)
- CPRINTS("C%d 0x%x last (%dmW %dmV) input (%dmW %dmV %dmA) "
- "avg (%dmW, %dmA)",
- active_port, flag, req_pwr, req_mv, input_pwr, vbus,
- input_curr, input_pwr_avg, input_curr_avg);
-
- for (int i = 0; i < board_get_usb_pd_port_count(); ++i) {
- const uint32_t * const src_caps = pd_get_src_caps(i);
-
- for (int j = 0; j < pd_get_src_cap_cnt(i); ++j) {
- int ma, mv, unused;
- int mw;
- bool efficient;
-
- /* TODO(b:169532537): support augmented PDO. */
- if ((src_caps[j] & PDO_TYPE_MASK) != PDO_TYPE_FIXED)
- continue;
-
- pd_extract_pdo_power(src_caps[j], &ma, &mv, &unused);
-
- if (mv > max_mv)
- continue;
-
- mw = ma * mv / 1000;
- efficient = is_more_efficient(mv, cand->mv, batt_mv,
- batt_pwr, input_pwr_avg);
-
- if (flag & DPS_FLAG_NEED_MORE_PWR) {
- /* the insufficient case.*/
- if (input_pwr_avg > cand->mw &&
- (mw > cand->mw ||
- (mw == cand->mw && efficient))) {
- UPDATE_CANDIDATE(i, mv, mw);
- } else if (input_pwr_avg <= mw && efficient) {
- UPDATE_CANDIDATE(i, mv, mw);
- }
- } else {
- int adjust_pwr =
- mw * dps_config.k_less_pwr / 100;
- int adjust_cand_mw =
- cand->mw * dps_config.k_less_pwr / 100;
-
- /* Pick if we don't have a candidate yet. */
- if (!cand->mw) {
- UPDATE_CANDIDATE(i, mv, mw);
- /*
- * if the candidate is insufficient, and
- * we get one provides more.
- */
- } else if ((adjust_cand_mw < input_pwr_avg &&
- cand->mw < mw) ||
- /*
- * if the candidate is sufficient,
- * and we pick a more efficient one.
- */
- (adjust_cand_mw >= input_pwr_avg &&
- adjust_pwr >= input_pwr_avg &&
- efficient)) {
- UPDATE_CANDIDATE(i, mv, mw);
- }
- }
-
-
- /*
- * if the candidate is the same as the current one, pick
- * the one at active charge port.
- */
- if (mw == cand->mw && mv == cand->mv &&
- i == active_port)
- UPDATE_CANDIDATE(i, mv, mw);
- }
- }
-
- if (!cand->mv)
- CPRINTS("ERR:CNDMV");
-
- return (cand->mv != req_mv);
-}
-
-static bool has_srccap(void)
-{
- for (int i = 0; i < board_get_usb_pd_port_count(); ++i) {
- if (pd_is_connected(i) &&
- pd_get_power_role(i) == PD_ROLE_SINK &&
- pd_get_src_cap_cnt(i) > 0)
- return true;
- }
- return false;
-}
-
-void dps_update_stabilized_time(int port)
-{
- update_timeout(dps_config.t_stable);
-}
-
-void dps_task(void *u)
-{
- struct pdo_candidate last_cand = {CHARGE_PORT_NONE, 0, 0};
- int sample_count = 0;
-
- dps_init();
- update_timeout(dps_config.t_check);
-
- while (1) {
- struct pdo_candidate curr_cand = {CHARGE_PORT_NONE, 0, 0};
- timestamp_t now;
-
- now = get_time();
- if (flag & DPS_FLAG_STOP_EVENTS) {
- dps_reset();
- task_wait_event(-1);
- /* clear flags after wake up. */
- flag = 0;
- update_timeout(dps_config.t_check);
- continue;
- } else if (now.val < timeout.val) {
- flag |= DPS_FLAG_WAITING;
- task_wait_event(timeout.val - now.val);
- flag &= ~DPS_FLAG_WAITING;
- }
-
- if (!is_enabled) {
- flag |= DPS_FLAG_DISABLED;
- continue;
- }
-
- if (!has_srccap()) {
- flag |= DPS_FLAG_NO_SRCCAP;
- continue;
- }
-
- if (!has_new_power_request(&curr_cand)) {
- sample_count = 0;
- flag &= ~DPS_FLAG_SAMPLED;
- } else {
- if (last_cand.port == curr_cand.port &&
- last_cand.mv == curr_cand.mv &&
- last_cand.mw == curr_cand.mw)
- sample_count++;
- else
- sample_count = 1;
- flag |= DPS_FLAG_SAMPLED;
- }
-
- if (sample_count == dps_config.k_sample) {
- dynamic_mv = curr_cand.mv;
- dps_port = curr_cand.port;
- pd_dpm_request(dps_port,
- DPM_REQUEST_NEW_POWER_LEVEL);
- sample_count = 0;
- flag &= ~(DPS_FLAG_SAMPLED | DPS_FLAG_NEED_MORE_PWR);
- }
-
- last_cand.port = curr_cand.port;
- last_cand.mv = curr_cand.mv;
- last_cand.mw = curr_cand.mw;
-
- update_timeout(dps_config.t_check);
- }
-}
-
-static int command_dps(int argc, char **argv)
-{
- int port = charge_manager_get_active_charge_port();
- int input_pwr, vbus, input_curr;
- int holder;
-
- if (argc == 1) {
- uint32_t last_ma = 0, last_mv = 0;
- int batt_mv;
-
- ccprintf("flag=0x%x k_more=%d k_less=%d k_sample=%d k_win=%d\n",
- flag, dps_config.k_more_pwr, dps_config.k_less_pwr,
- dps_config.k_sample, dps_config.k_window);
- ccprintf("t_stable=%d t_check=%d\n",
- dps_config.t_stable / SECOND,
- dps_config.t_check / SECOND);
- if (!is_enabled) {
- ccprintf("DPS Disabled\n");
- return EC_SUCCESS;
- }
-
- if (port == CHARGE_PORT_NONE) {
- ccprintf("No charger attached\n");
- return EC_SUCCESS;
- }
-
- battery_design_voltage(&batt_mv);
- input_pwr = get_desired_input_power(&vbus, &input_curr);
- if (!(flag & DPS_FLAG_NO_SRCCAP)) {
- last_mv = pd_get_requested_voltage(port);
- last_ma = pd_get_requested_current(port);
- }
- ccprintf("C%d DPS Enabled\n"
- "Requested: %dmV/%dmA\n"
- "Measured: %dmV/%dmA/%dmW\n"
- "Efficient: %dmV\n"
- "Batt: %dmv\n"
- "PDMaxMV: %dmV\n",
- port, last_mv, last_ma,
- vbus, input_curr, input_pwr,
- get_efficient_voltage(),
- batt_mv,
- pd_get_max_voltage());
- return EC_SUCCESS;
- }
-
- if (!strcasecmp(argv[1], "en")) {
- dps_enable(true);
- return EC_SUCCESS;
- } else if (!strcasecmp(argv[1], "dis")) {
- dps_enable(false);
- return EC_SUCCESS;
- } else if (!strcasecmp(argv[1], "fakepwr")) {
- if (argc == 2) {
- ccprintf("%sabled %dmV/%dmA\n",
- fake_enabled ? "en" : "dis", fake_mv, fake_ma);
- return EC_SUCCESS;
- }
-
- if (!strcasecmp(argv[2], "dis")) {
- fake_enabled = false;
- return EC_SUCCESS;
- }
-
- if (argc < 4)
- return EC_ERROR_PARAM_COUNT;
-
- holder = atoi(argv[2]);
- if (holder <= 0)
- return EC_ERROR_PARAM2;
- fake_mv = holder;
-
- holder = atoi(argv[3]);
- if (holder <= 0)
- return EC_ERROR_PARAM3;
- fake_ma = holder;
-
- fake_enabled = true;
- return EC_SUCCESS;
- }
-
- if (argc != 3)
- return EC_ERROR_PARAM2;
-
- if (!strcasecmp(argv[1], "debug")) {
- debug_level = atoi(argv[2]);
- } else if (!strcasecmp(argv[1], "setkmore")) {
- holder = atoi(argv[2]);
- if (holder > 100 || holder <= 0 ||
- holder < dps_config.k_less_pwr)
- return EC_ERROR_PARAM2;
- dps_config.k_more_pwr = holder;
- } else if (!strcasecmp(argv[1], "setkless")) {
- holder = atoi(argv[2]);
- if (holder > 100 || holder <= 0 ||
- holder > dps_config.k_more_pwr)
- return EC_ERROR_PARAM2;
- dps_config.k_less_pwr = holder;
- } else if (!strcasecmp(argv[1], "setksample")) {
- holder = atoi(argv[2]);
- if (holder <= 0)
- return EC_ERROR_PARAM2;
- dps_config.k_sample = holder;
- } else if (!strcasecmp(argv[1], "setkwin")) {
- holder = atoi(argv[2]);
- if (holder <= 0 || holder > MAX_MOVING_AVG_WINDOW)
- return EC_ERROR_PARAM2;
- dps_config.k_window = holder;
- } else if (!strcasecmp(argv[1], "settcheck")) {
- holder = atoi(argv[2]);
- if (holder <= 0)
- return EC_ERROR_PARAM2;
- dps_config.t_check = holder * SECOND;
- } else if (!strcasecmp(argv[1], "settstable")) {
- holder = atoi(argv[2]);
- if (holder <= 0)
- return EC_ERROR_PARAM2;
- dps_config.t_stable = holder * SECOND;
- } else {
- return EC_ERROR_PARAM1;
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(dps, command_dps,
- "en|dis|debug <int>\n"
- "\t\t set(kmore|kless|ksample|kwindow) <int>\n"
- "\t\t set(tstable|tcheck) <int>\n"
- "\t\t fakepwr [dis|<mV> <mA>]",
- "Print/set Dynamic PDO Selection state.");
diff --git a/common/dptf.c b/common/dptf.c
deleted file mode 100644
index 33a42ba5af..0000000000
--- a/common/dptf.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/* Copyright 2016 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.
- */
-
-#include "atomic.h"
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "dptf.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "temp_sensor.h"
-#include "util.h"
-
-#ifdef CONFIG_ZEPHYR
-#include "temp_sensor/temp_sensor.h"
-#endif
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_DPTF, outstr)
-#define CPRINTS(format, args...) cprints(CC_DPTF, format, ## args)
-
-/*****************************************************************************/
-/* DPTF temperature thresholds */
-
-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 void dptf_init(void)
-{
- int id, t;
-
- for (id = 0; id < TEMP_SENSOR_COUNT; id++)
- for (t = 0; t < DPTF_THRESHOLDS_PER_SENSOR; t++) {
- dptf_threshold[id][t].temp = -1;
- cond_init(&dptf_threshold[id][t].over, 0);
- }
-
-}
-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;
-
-int dptf_query_next_sensor_event(void)
-{
- int id;
-
- for (id = 0; id < TEMP_SENSOR_COUNT; id++)
- if (dptf_seen & BIT(id)) { /* atomic? */
- atomic_clear_bits(&dptf_seen, BIT(id));
- return id;
- }
-
- return -1;
-}
-
-/* Return true if any threshold transition occurs. */
-static int dptf_check_temp_threshold(int sensor_id, int temp)
-{
- int tripped = 0;
- int max, i;
-
- if (sensor_id >= TEMP_SENSOR_COUNT) {
- CPRINTS("DPTF: Invalid sensor ID");
- return 0;
- }
-
- for (i = 0; i < DPTF_THRESHOLDS_PER_SENSOR; i++) {
-
- max = dptf_threshold[sensor_id][i].temp;
- if (max < 0) /* disabled? */
- continue;
-
- if (temp >= max)
- cond_set_true(&dptf_threshold[sensor_id][i].over);
- else if (temp <= max - DPTF_THRESHOLD_HYSTERESIS)
- cond_set_false(&dptf_threshold[sensor_id][i].over);
-
- if (cond_went_true(&dptf_threshold[sensor_id][i].over)) {
- CPRINTS("DPTF over threshold [%d][%d",
- sensor_id, i);
- atomic_or(&dptf_seen, BIT(sensor_id));
- tripped = 1;
- }
- if (cond_went_false(&dptf_threshold[sensor_id][i].over)) {
- CPRINTS("DPTF under threshold [%d][%d",
- sensor_id, i);
- atomic_or(&dptf_seen, BIT(sensor_id));
- tripped = 1;
- }
- }
-
- return tripped;
-}
-
-void dptf_set_temp_threshold(int sensor_id, int temp, int idx, int enable)
-{
- CPRINTS("DPTF sensor %d, threshold %d C, index %d, %sabled",
- sensor_id, K_TO_C(temp), idx, enable ? "en" : "dis");
-
- if ((sensor_id >= TEMP_SENSOR_COUNT) ||
- (idx >= DPTF_THRESHOLDS_PER_SENSOR)) {
- CPRINTS("DPTF: Invalid sensor ID");
- return;
- }
-
- if (enable) {
- /* Don't update threshold condition if already enabled */
- if (dptf_threshold[sensor_id][idx].temp == -1)
- cond_init(&dptf_threshold[sensor_id][idx].over, 0);
- dptf_threshold[sensor_id][idx].temp = temp;
- atomic_clear_bits(&dptf_seen, BIT(sensor_id));
- } else {
- dptf_threshold[sensor_id][idx].temp = -1;
- }
-}
-
-/*****************************************************************************/
-/* EC-specific thermal controls */
-
-test_mockable_static void smi_sensor_failure_warning(void)
-{
- CPRINTS("can't read any temp sensors!");
- host_set_single_event(EC_HOST_EVENT_THERMAL);
-}
-
-static void thermal_control_dptf(void)
-{
- int i, t, rv;
- int dptf_tripped;
- int num_sensors_read;
-
- dptf_tripped = 0;
- num_sensors_read = 0;
-
- /* go through all the sensors */
- for (i = 0; i < TEMP_SENSOR_COUNT; ++i) {
- rv = temp_sensor_read(i, &t);
- if (rv != EC_SUCCESS)
- continue;
- else
- num_sensors_read++;
- /* and check the dptf thresholds */
- dptf_tripped |= dptf_check_temp_threshold(i, t);
- }
-
- if (!num_sensors_read) {
- /*
- * Trigger a SMI event if we can't read any sensors.
- *
- * In theory we could do something more elaborate like forcing
- * the system to shut down if no sensors are available after
- * several retries. This is a very unlikely scenario -
- * particularly on LM4-based boards, since the LM4 has its own
- * internal temp sensor. It's most likely to occur during
- * bringup of a new board, where we haven't debugged the I2C
- * bus to the sensors; forcing a shutdown in that case would
- * merely hamper board bringup.
- */
- if (!chipset_in_state(CHIPSET_STATE_HARD_OFF))
- smi_sensor_failure_warning();
- }
-
- /* Don't forget to signal any DPTF thresholds */
- if (dptf_tripped)
- host_set_single_event(EC_HOST_EVENT_THERMAL_THRESHOLD);
-}
-
-/* Wait until after the sensors have been read */
-DECLARE_HOOK(HOOK_SECOND, thermal_control_dptf, HOOK_PRIO_TEMP_SENSOR_DONE);
-
-/*****************************************************************************/
-/* Console commands */
-
-static int command_dptftemp(int argc, char **argv)
-{
- int id, t;
- int temp, trig;
-
- ccprintf("sensor thresh0 thresh1\n");
- for (id = 0; id < TEMP_SENSOR_COUNT; id++) {
- ccprintf(" %2d", id);
- for (t = 0; t < DPTF_THRESHOLDS_PER_SENSOR; t++) {
- temp = dptf_threshold[id][t].temp;
- trig = cond_is_true(&dptf_threshold[id][t].over);
- if (temp < 0)
- ccprintf(" --- ");
- else
- ccprintf(" %3d%c", temp,
- trig ? '*' : ' ');
- }
- ccprintf(" %s\n", temp_sensors[id].name);
- }
-
- ccprintf("AP seen mask: 0x%08x\n", dptf_seen);
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(dptftemp, command_dptftemp,
- NULL,
- "Print DPTF thermal parameters (degrees Kelvin)");
diff --git a/common/ec.libsharedobjs.ld b/common/ec.libsharedobjs.ld
deleted file mode 100644
index adf5081640..0000000000
--- a/common/ec.libsharedobjs.ld
+++ /dev/null
@@ -1,15 +0,0 @@
-/* Copyright 2015 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.
- */
-
-SECTIONS
-{
- .roshared : { KEEP(*(.roshared*)) }
- /*
- * Save the .ARM.atrributes section to make the linker not complain
- * about conflicting CPU architectures when linking with the RW objs.
- * This section will be discarded by the main EC linker script.
- */
- .ARM.attributes : { KEEP(*(.ARM.*)) }
-}
diff --git a/common/ec_ec_comm_client.c b/common/ec_ec_comm_client.c
deleted file mode 100644
index c92433af8c..0000000000
--- a/common/ec_ec_comm_client.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/* Copyright 2017 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.
- *
- * EC-EC communication, functions and definitions for client.
- */
-
-#include "battery.h"
-#include "common.h"
-#include "console.h"
-#include "crc8.h"
-#include "ec_commands.h"
-#include "ec_ec_comm_client.h"
-#include "timer.h"
-#include "uart.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args)
-
-/*
- * TODO(b:65697962): The packed structures below do not play well if we force EC
- * host commands structures to be aligned on 32-bit boundary. There are ways to
- * fix that, possibly requiring copying data around, or modifying
- * uart_alt_pad_write_read API to write the actual server response to a separate
- * buffer.
- */
-#ifdef CONFIG_HOSTCMD_ALIGNED
-#error "Cannot define CONFIG_HOSTCMD_ALIGNED with EC-EC communication client."
-#endif
-
-#define EC_EC_HOSTCMD_VERSION 4
-
-/* Print extra debugging information */
-#undef EXTRA_DEBUG
-
-/*
- * During early debugging, we would like to check that the error rate does
- * grow out of control.
- */
-#define DEBUG_EC_COMM_STATS
-#ifdef DEBUG_EC_COMM_STATS
-struct {
- int total;
- int errtimeout;
- int errbusy;
- int errunknown;
- int errdatacrc;
- int errcrc;
- int errinval;
-} comm_stats;
-
-#define INCR_COMM_STATS(var) (comm_stats.var++)
-#else
-#define INCR_COMM_STATS(var)
-#endif
-
-/**
- * Write a command on the EC-EC communication UART channel.
- *
- * @param command One of EC_CMD_*.
- * @param data Packed structure with this layout:
- * struct {
- * struct {
- * struct ec_host_request4 head;
- * struct ec_params_* param;
- * uint8_t crc8;
- * } req;
- * struct {
- * struct ec_host_response4 head;
- * struct ec_response_* info;
- * uint8_t crc8;
- * } resp;
- * } __packed data;
- *
- * Where req is the request to be transmitted (head and crc8 are computed by
- * this function), and resp is the response to be received (head integrity and
- * crc8 are verified by this function).
- *
- * This format is required as the EC-EC UART is half-duplex, and all the
- * transmitted data is received back, i.e. the client writes req, then reads
- * req, followed by resp.
- *
- * When a command does not take parameters, param/crc8 must be omitted in
- * tx structure. The same applies to rx structure if the response does not
- * include a payload: info/crc8 must be omitted.
- *
- * @param req_len size of req.param (0 if no parameter is passed).
- * @param resp_len size of resp.info (0 if no information is returned).
- * @param timeout_us timeout in microseconds for the transaction to complete.
- *
- * @return
- * - EC_SUCCESS on success.
- * - EC_ERROR_TIMEOUT when remote end times out replying.
- * - EC_ERROR_BUSY when UART is busy and cannot transmit currently.
- * - EC_ERROR_CRC when the header or data CRC is invalid.
- * - EC_ERROR_INVAL when the received header is invalid.
- * - EC_ERROR_UNKNOWN on other error.
- */
-static int write_command(uint16_t command,
- uint8_t *data, int req_len, int resp_len,
- int timeout_us)
-{
- /* Sequence number. */
- static uint8_t cur_seq;
- int ret;
- int hascrc, response_seq;
-
- struct ec_host_request4 *request_header = (void *)data;
- /* Request (TX) length is header + (data + crc8), response follows. */
- int tx_length =
- sizeof(*request_header) + ((req_len > 0) ? (req_len + 1) : 0);
-
- struct ec_host_response4 *response_header =
- (void *)&data[tx_length];
- /* RX length is TX length + response from server. */
- int rx_length = tx_length +
- sizeof(*request_header) + ((resp_len > 0) ? (resp_len + 1) : 0);
-
- /*
- * Make sure there is a gap between each command, so that the server
- * can recover its state machine after each command.
- *
- * TODO(b:65697962): We can be much smarter than this, and record the
- * last transaction time instead of just sleeping blindly.
- */
- usleep(10*MSEC);
-
-#ifdef DEBUG_EC_COMM_STATS
- if ((comm_stats.total % 128) == 0) {
- CPRINTF("UART %d (T%dB%d,U%dC%dD%dI%d)\n", comm_stats.total,
- comm_stats.errtimeout, comm_stats.errbusy,
- comm_stats.errunknown, comm_stats.errcrc,
- comm_stats.errdatacrc, comm_stats.errinval);
- }
-#endif
-
- cur_seq = (cur_seq + 1) &
- (EC_PACKET4_0_SEQ_NUM_MASK >> EC_PACKET4_0_SEQ_NUM_SHIFT);
-
- memset(request_header, 0, sizeof(*request_header));
- /* fields0: leave seq_dup and is_response as 0. */
- request_header->fields0 =
- EC_EC_HOSTCMD_VERSION | /* version */
- (cur_seq << EC_PACKET4_0_SEQ_NUM_SHIFT); /* seq_num */
- /* fields1: leave command_version as 0. */
- if (req_len > 0)
- request_header->fields1 |= EC_PACKET4_1_DATA_CRC_PRESENT_MASK;
- request_header->command = command;
- request_header->data_len = req_len;
- request_header->header_crc =
- cros_crc8((uint8_t *)request_header, sizeof(*request_header)-1);
- if (req_len > 0)
- data[sizeof(*request_header) + req_len] =
- cros_crc8(&data[sizeof(*request_header)], req_len);
-
- ret = uart_alt_pad_write_read((void *)data, tx_length,
- (void *)data, rx_length, timeout_us);
-
- INCR_COMM_STATS(total);
-
-#ifdef EXTRA_DEBUG
- CPRINTF("EC-EC ret=%d/%d\n", ret, rx_length);
-#endif
-
- if (ret != rx_length) {
- if (ret == -EC_ERROR_TIMEOUT) {
- INCR_COMM_STATS(errtimeout);
- return EC_ERROR_TIMEOUT;
- }
-
- if (ret == -EC_ERROR_BUSY) {
- INCR_COMM_STATS(errbusy);
- return EC_ERROR_BUSY;
- }
-
- INCR_COMM_STATS(errunknown);
- return EC_ERROR_UNKNOWN;
- }
-
- if (response_header->header_crc !=
- cros_crc8((uint8_t *)response_header,
- sizeof(*response_header) - 1)) {
- INCR_COMM_STATS(errcrc);
- return EC_ERROR_CRC;
- }
-
- hascrc = response_header->fields1 & EC_PACKET4_1_DATA_CRC_PRESENT_MASK;
- response_seq = (response_header->fields0 & EC_PACKET4_0_SEQ_NUM_MASK) >>
- EC_PACKET4_0_SEQ_NUM_SHIFT;
-
- /*
- * Validate received header.
- * Note that we _require_ data crc to be present if there is data to be
- * read back, else we would not know how many bytes to read exactly.
- */
- if ((response_header->fields0 & EC_PACKET4_0_STRUCT_VERSION_MASK)
- != EC_EC_HOSTCMD_VERSION ||
- !(response_header->fields0 &
- EC_PACKET4_0_IS_RESPONSE_MASK) ||
- response_seq != cur_seq ||
- (response_header->data_len > 0 && !hascrc) ||
- response_header->data_len != resp_len) {
- INCR_COMM_STATS(errinval);
- return EC_ERROR_INVAL;
- }
-
- /* Check data CRC. */
- if (hascrc &&
- data[rx_length - 1] !=
- cros_crc8(&data[tx_length + sizeof(*request_header)],
- resp_len)) {
- INCR_COMM_STATS(errdatacrc);
- return EC_ERROR_CRC;
- }
-
- return EC_SUCCESS;
-}
-
-/**
- * handle error from write_command
- *
- * @param ret is return value from write_command
- * @param request_result is data.resp.head.result (response result value)
- *
- * @return EC_RES_ERROR if ret is not EC_SUCCESS, else request_result.
- */
-static int handle_error(const char *func, int ret, int request_result)
-{
- if (ret != EC_SUCCESS) {
- /* Do not print busy errors as they just spam the console. */
- if (ret != EC_ERROR_BUSY)
- CPRINTF("%s: tx error %d\n", func, ret);
- return EC_RES_ERROR;
- }
-
- if (request_result != EC_RES_SUCCESS)
- CPRINTF("%s: cmd error %d\n", func, ret);
-
- return request_result;
-}
-
-#ifdef CONFIG_EC_EC_COMM_BATTERY
-int ec_ec_client_base_get_dynamic_info(void)
-{
- int ret;
- struct {
- struct {
- struct ec_host_request4 head;
- struct ec_params_battery_dynamic_info param;
- uint8_t crc8;
- } req;
- struct {
- struct ec_host_response4 head;
- struct ec_response_battery_dynamic_info info;
- uint8_t crc8;
- } resp;
- } __packed data;
-
- data.req.param.index = 0;
-
- ret = write_command(EC_CMD_BATTERY_GET_DYNAMIC,
- (void *)&data, sizeof(data.req.param),
- sizeof(data.resp.info), 15 * MSEC);
- ret = handle_error(__func__, ret, data.resp.head.result);
- if (ret != EC_RES_SUCCESS)
- return ret;
-
-#ifdef EXTRA_DEBUG
- CPRINTF("V: %d mV\n", data.resp.info.actual_voltage);
- CPRINTF("I: %d mA\n", data.resp.info.actual_current);
- CPRINTF("Remaining: %d mAh\n", data.resp.info.remaining_capacity);
- CPRINTF("Cap-full: %d mAh\n", data.resp.info.full_capacity);
- CPRINTF("Flags: %04x\n", data.resp.info.flags);
- CPRINTF("V-desired: %d mV\n", data.resp.info.desired_voltage);
- CPRINTF("I-desired: %d mA\n", data.resp.info.desired_current);
-#endif
-
- memcpy(&battery_dynamic[BATT_IDX_BASE], &data.resp.info,
- sizeof(battery_dynamic[BATT_IDX_BASE]));
- return EC_RES_SUCCESS;
-}
-
-int ec_ec_client_base_get_static_info(void)
-{
- int ret;
- struct {
- struct {
- struct ec_host_request4 head;
- struct ec_params_battery_static_info param;
- uint8_t crc8;
- } req;
- struct {
- struct ec_host_response4 head;
- struct ec_response_battery_static_info info;
- uint8_t crc8;
- } resp;
- } __packed data;
-
- data.req.param.index = 0;
-
- ret = write_command(EC_CMD_BATTERY_GET_STATIC,
- (void *)&data, sizeof(data.req.param),
- sizeof(data.resp.info), 15 * MSEC);
- ret = handle_error(__func__, ret, data.resp.head.result);
- if (ret != EC_RES_SUCCESS)
- return ret;
-
-#ifdef EXTRA_DEBUG
- CPRINTF("Cap-design: %d mAh\n", data.resp.info.design_capacity);
- CPRINTF("V-design: %d mV\n", data.resp.info.design_voltage);
- CPRINTF("Manuf: %s\n", data.resp.info.manufacturer);
- CPRINTF("Model: %s\n", data.resp.info.model);
- CPRINTF("Serial: %s\n", data.resp.info.serial);
- CPRINTF("Type: %s\n", data.resp.info.type);
- CPRINTF("C-count: %d\n", data.resp.info.cycle_count);
-#endif
-
- memcpy(&battery_static[BATT_IDX_BASE], &data.resp.info,
- sizeof(battery_static[BATT_IDX_BASE]));
- return EC_RES_SUCCESS;
-}
-
-int ec_ec_client_base_charge_control(int max_current,
- int otg_voltage,
- int allow_charging)
-{
- int ret;
- struct {
- struct {
- struct ec_host_request4 head;
- struct ec_params_charger_control ctrl;
- uint8_t crc8;
- } req;
- struct {
- struct ec_host_response4 head;
- } resp;
- } __packed data;
-
- data.req.ctrl.allow_charging = allow_charging;
- data.req.ctrl.max_current = max_current;
- data.req.ctrl.otg_voltage = otg_voltage;
-
- ret = write_command(EC_CMD_CHARGER_CONTROL,
- (void *)&data, sizeof(data.req.ctrl), 0, 30 * MSEC);
-
- return handle_error(__func__, ret, data.resp.head.result);
-}
-
-int ec_ec_client_hibernate(void)
-{
- int ret;
- struct {
- struct {
- struct ec_host_request4 head;
- struct ec_params_reboot_ec param;
- } req;
- struct {
- struct ec_host_response4 head;
- } resp;
- } __packed data;
-
- data.req.param.cmd = EC_REBOOT_HIBERNATE;
- data.req.param.flags = 0;
-
- ret = write_command(EC_CMD_REBOOT_EC,
- (void *)&data, sizeof(data.req.param), 0, 30 * MSEC);
-
- return handle_error(__func__, ret, data.resp.head.result);
-}
-#endif /* CONFIG_EC_EC_COMM_BATTERY */
diff --git a/common/ec_ec_comm_server.c b/common/ec_ec_comm_server.c
deleted file mode 100644
index 23b5fee139..0000000000
--- a/common/ec_ec_comm_server.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/* Copyright 2017 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.
- *
- * EC-EC communication, task and functions for server.
- */
-
-#include "common.h"
-#include "battery.h"
-#include "charge_state_v2.h"
-#include "console.h"
-#include "crc8.h"
-#include "ec_commands.h"
-#include "ec_ec_comm_server.h"
-#include "extpower.h"
-#include "hwtimer.h"
-#include "hooks.h"
-#include "queue.h"
-#include "queue_policies.h"
-#include "system.h"
-#include "task.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args)
-
-/* Print extra debugging information */
-#undef EXTRA_DEBUG
-
-/* Set if the client allows the server to charge the battery. */
-static int charging_allowed;
-
-/*
- * Our command parameter buffer must be big enough to fit any command
- * parameter, and crc byte.
- */
-#define LARGEST_PARAMS_SIZE 8
-
-BUILD_ASSERT(LARGEST_PARAMS_SIZE >=
- sizeof(struct ec_params_battery_static_info));
-BUILD_ASSERT(LARGEST_PARAMS_SIZE >=
- sizeof(struct ec_params_battery_dynamic_info));
-BUILD_ASSERT(LARGEST_PARAMS_SIZE >=
- sizeof(struct ec_params_charger_control));
-
-#define COMMAND_BUFFER_PARAMS_SIZE (LARGEST_PARAMS_SIZE + 1)
-
-/*
- * Maximum time needed to read a full command, commands are at most 17 bytes, so
- * should not take more than 2ms to be sent at 115200 bps.
- */
-#define COMMAND_TIMEOUT_US (5 * MSEC)
-
-
-void ec_ec_comm_server_written(struct consumer const *consumer, size_t count)
-{
- task_wake(TASK_ID_ECCOMM);
-}
-
-/*
- * Discard all data from the input queue.
- *
- * Note that we always sleep for 1ms after clearing the queue, to make sure
- * that we give enough time for the next byte to arrive.
- */
-static void discard_queue(void)
-{
- do {
- queue_advance_head(&ec_ec_comm_server_input,
- queue_count(&ec_ec_comm_server_input));
- usleep(1 * MSEC);
- } while (queue_count(&ec_ec_comm_server_input) > 0);
-}
-
-/* Write response to client. */
-static void write_response(uint16_t res, int seq, const void *data, int len)
-{
- struct ec_host_response4 header;
- uint8_t crc;
-
- header.fields0 =
- 4 | /* version */
- EC_PACKET4_0_IS_RESPONSE_MASK | /* is_response */
- (seq << EC_PACKET4_0_SEQ_NUM_SHIFT); /* seq_num */
- /* Set data_crc_present if there is data */
- header.fields1 = (len > 0) ? EC_PACKET4_1_DATA_CRC_PRESENT_MASK : 0;
- header.result = res;
- header.data_len = len;
- header.reserved = 0;
- header.header_crc =
- cros_crc8((uint8_t *)&header, sizeof(header)-1);
- QUEUE_ADD_UNITS(&ec_ec_comm_server_output,
- (uint8_t *)&header, sizeof(header));
-
- if (len > 0) {
- QUEUE_ADD_UNITS(&ec_ec_comm_server_output, data, len);
- crc = cros_crc8(data, len);
- QUEUE_ADD_UNITS(&ec_ec_comm_server_output, &crc, sizeof(crc));
- }
-}
-
-/*
- * Read len bytes into buffer. Waiting up to COMMAND_TIMEOUT_US after start.
- *
- * Returns EC_SUCCESS or EC_ERROR_TIMEOUT.
- */
-static int read_data(void *buffer, size_t len, uint32_t start)
-{
- uint32_t delta;
-
- while (queue_count(&ec_ec_comm_server_input) < len) {
- delta = __hw_clock_source_read() - start;
- if (delta >= COMMAND_TIMEOUT_US)
- return EC_ERROR_TIMEOUT;
-
- /* Every incoming byte wakes the task. */
- task_wait_event(COMMAND_TIMEOUT_US - delta);
- }
-
- /* Fetch header */
- QUEUE_REMOVE_UNITS(&ec_ec_comm_server_input, buffer, len);
-
- return EC_SUCCESS;
-}
-
-static void handle_cmd_reboot_ec(
- const struct ec_params_reboot_ec *params,
- int data_len, int seq)
-{
- int ret = EC_RES_SUCCESS;
-
- if (data_len != sizeof(*params)) {
- ret = EC_RES_INVALID_COMMAND;
- goto out;
- }
-
- /* Only handle hibernate */
- if (params->cmd != EC_REBOOT_HIBERNATE) {
- ret = EC_RES_INVALID_PARAM;
- goto out;
- }
-
- CPRINTS("Hibernating...");
-
- system_hibernate(0, 0);
- /* We should not be able to write back the response. */
-
-out:
- write_response(ret, seq, NULL, 0);
-}
-
-#ifdef CONFIG_EC_EC_COMM_BATTERY
-static void handle_cmd_charger_control(
- const struct ec_params_charger_control *params,
- int data_len, int seq)
-{
- int ret = EC_RES_SUCCESS;
- int prev_charging_allowed = charging_allowed;
-
- if (data_len != sizeof(*params)) {
- ret = EC_RES_INVALID_COMMAND;
- goto out;
- }
-
- if (params->max_current >= 0) {
- charge_set_output_current_limit(CHARGER_SOLO, 0, 0);
- charge_set_input_current_limit(
- MIN(MAX_CURRENT_MA, params->max_current), 0);
- charging_allowed = params->allow_charging;
- } else {
- if (-params->max_current > MAX_OTG_CURRENT_MA ||
- params->otg_voltage > MAX_OTG_VOLTAGE_MV) {
- ret = EC_RES_INVALID_PARAM;
- goto out;
- }
-
- /* Reset input current to minimum. */
- charge_set_input_current_limit(CONFIG_CHARGER_INPUT_CURRENT, 0);
- /* Setup and enable "OTG". */
- charge_set_output_current_limit(CHARGER_SOLO,
- -params->max_current,
- params->otg_voltage);
- charging_allowed = 0;
- }
-
- if (prev_charging_allowed != charging_allowed)
- hook_notify(HOOK_AC_CHANGE);
-
-out:
- write_response(ret, seq, NULL, 0);
-}
-
-/*
- * On dual-battery server, we use the charging allowed signal from client to
- * indicate whether external power is present.
- *
- * In most cases, this actually matches the external power status of the client
- * (server battery charging when AC is connected, or discharging when server
- * battery still has enough capacity), with one exception: when we do client to
- * server battery charging (in this case the "external" power is the client).
- */
-int extpower_is_present(void)
-{
- return charging_allowed;
-}
-#endif
-
-void ec_ec_comm_server_task(void *u)
-{
- struct ec_host_request4 header;
- /*
- * If CONFIG_HOSTCMD_ALIGNED is set, it is important that params is
- * aligned on a 32-bit boundary.
- */
- uint8_t __aligned(4) params[COMMAND_BUFFER_PARAMS_SIZE];
- unsigned int len, seq = 0, hascrc, cmdver;
- uint32_t start;
-
- while (1) {
- task_wait_event(-1);
-
- if (queue_count(&ec_ec_comm_server_input) == 0)
- continue;
-
- /* We got some data, start timeout counter. */
- start = __hw_clock_source_read();
-
- /* Wait for whole header to be available and read it. */
- if (read_data(&header, sizeof(header), start)) {
- CPRINTS("%s timeout (header)", __func__);
- goto discard;
- }
-
-#ifdef EXTRA_DEBUG
- CPRINTS("%s f0=%02x f1=%02x cmd=%02x, length=%d", __func__,
- header.fields0, header.fields1,
- header.command, header.data_len);
-#endif
-
- /* Ignore response (we wrote that ourselves) */
- if (header.fields0 & EC_PACKET4_0_IS_RESPONSE_MASK)
- goto discard;
-
- /* Validate version and crc. */
- if ((header.fields0 & EC_PACKET4_0_STRUCT_VERSION_MASK) != 4 ||
- header.header_crc !=
- cros_crc8((uint8_t *)&header, sizeof(header) - 1)) {
- CPRINTS("%s header/crc error", __func__);
- goto discard;
- }
-
- len = header.data_len;
- hascrc = header.fields1 & EC_PACKET4_1_DATA_CRC_PRESENT_MASK;
- if (hascrc)
- len += 1;
-
- /*
- * Ignore commands that are too long to fit in our buffer.
- */
- if (len > sizeof(params)) {
- CPRINTS("%s len error (%d)", __func__, len);
- /* Discard the data first, then write error back. */
- discard_queue();
- write_response(EC_RES_OVERFLOW, seq, NULL, 0);
- goto discard;
- }
-
- seq = (header.fields0 & EC_PACKET4_0_SEQ_NUM_MASK) >>
- EC_PACKET4_0_SEQ_NUM_SHIFT;
-
- cmdver = header.fields1 & EC_PACKET4_1_COMMAND_VERSION_MASK;
-
- /* Wait for the rest of the data to be available and read it. */
- if (read_data(params, len, start)) {
- CPRINTS("%s timeout (data)", __func__);
- goto discard;
- }
-
- /* Check data CRC */
- if (hascrc && params[len-1] != cros_crc8(params, len-1)) {
- CPRINTS("%s data crc error", __func__);
- write_response(EC_RES_INVALID_CHECKSUM, seq, NULL, 0);
- goto discard;
- }
-
- /* For now, all commands have version 0. */
- if (cmdver != 0) {
- CPRINTS("%s bad command version", __func__);
- write_response(EC_RES_INVALID_VERSION, seq, NULL, 0);
- continue;
- }
-
- switch (header.command) {
-#ifdef CONFIG_EC_EC_COMM_BATTERY
- case EC_CMD_BATTERY_GET_STATIC:
- /* Note that we ignore the battery index parameter. */
- write_response(EC_RES_SUCCESS, seq,
- &battery_static[BATT_IDX_MAIN],
- sizeof(battery_static[BATT_IDX_MAIN]));
- break;
- case EC_CMD_BATTERY_GET_DYNAMIC:
- /* Note that we ignore the battery index parameter. */
- write_response(EC_RES_SUCCESS, seq,
- &battery_dynamic[BATT_IDX_MAIN],
- sizeof(battery_dynamic[BATT_IDX_MAIN]));
- break;
- case EC_CMD_CHARGER_CONTROL:
- handle_cmd_charger_control((void *)params,
- header.data_len, seq);
- break;
-#endif
- case EC_CMD_REBOOT_EC:
- handle_cmd_reboot_ec((void *)params,
- header.data_len, seq);
- break;
- default:
- write_response(EC_RES_INVALID_COMMAND, seq,
- NULL, 0);
- }
-
- continue;
-discard:
- /*
- * Some error occurred: discard all data in the queue.
- */
- discard_queue();
- }
-}
diff --git a/common/espi.c b/common/espi.c
deleted file mode 100644
index 0a747d3bda..0000000000
--- a/common/espi.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Copyright 2017 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.
- */
-
-/* eSPI common functionality for Chrome EC */
-
-#include "common.h"
-#include "gpio.h"
-#include "registers.h"
-#include "espi.h"
-#include "timer.h"
-#include "util.h"
-
-
-const char *espi_vw_names[] = {
- "VW_SLP_S3_L",
- "VW_SLP_S4_L",
- "VW_SLP_S5_L",
- "VW_SUS_STAT_L",
- "VW_PLTRST_L",
- "VW_OOB_RST_WARN",
- "VW_OOB_RST_ACK",
- "VW_WAKE_L",
- "VW_PME_L",
- "VW_ERROR_FATAL",
- "VW_ERROR_NON_FATAL",
- /* Merge bit 3/0 into one signal. Need to set them simultaneously */
- "VW_PERIPHERAL_BTLD_STATUS_DONE",
- "VW_SCI_L",
- "VW_SMI_L",
- "VW_RCIN_L",
- "VW_HOST_RST_ACK",
- "VW_HOST_RST_WARN",
- "VW_SUS_ACK",
- "VW_SUS_WARN_L",
- "VW_SUS_PWRDN_ACK_L",
- "VW_SLP_A_L",
- "VW_SLP_LAN",
- "VW_SLP_WLAN",
-};
-BUILD_ASSERT(ARRAY_SIZE(espi_vw_names) == VW_SIGNAL_COUNT);
-
-
-const char *espi_vw_get_wire_name(enum espi_vw_signal signal)
-{
- if (espi_signal_is_vw(signal))
- return espi_vw_names[signal - VW_SIGNAL_START];
-
- return NULL;
-}
-
-
-int espi_signal_is_vw(int signal)
-{
- return ((signal >= VW_SIGNAL_START) && (signal < VW_SIGNAL_END));
-}
diff --git a/common/event_log.c b/common/event_log.c
deleted file mode 100644
index 95e44413bc..0000000000
--- a/common/event_log.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/* Copyright 2017 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.
- */
-
-#include "common.h"
-#include "console.h"
-#include "event_log.h"
-#include "hooks.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-
-/* Event log FIFO */
-#define UNIT_SIZE sizeof(struct event_log_entry)
-#define UNIT_COUNT (CONFIG_EVENT_LOG_SIZE/UNIT_SIZE)
-#define UNIT_COUNT_MASK (UNIT_COUNT - 1)
-static struct event_log_entry __bss_slow log_events[UNIT_COUNT];
-BUILD_ASSERT(POWER_OF_TWO(UNIT_COUNT));
-
-/*
- * The FIFO pointers are defined as following :
- * "log_head" is the next available event to dequeue.
- * "log_tail" is marking the end of the FIFO content (after last committed
- * event)
- * "log_tail_next" is the next available spot to enqueue events.
- * The pointers are not wrapped until they are used, so we don't need an extra
- * entry to disambiguate between full and empty FIFO.
- *
- * For concurrency, several tasks might try to enqueue events in parallel with
- * log_add_event(). Only one task is dequeuing events (host commands, VDM,
- * TPM command handler). When the FIFO is full, log_add_event() will discard
- * the oldest events, so "log_head" is incremented/decremented in a critical
- * section since it is accessed from both log_add_event() and
- * log_dequeue_event(). log_tail_next is also protected as several writers can
- * race to add an event to the queue.
- * When a writer is done adding its event, it is updating log_tail,
- * so the event can be consumed by log_dequeue_event().
- */
-static size_t log_head;
-static size_t log_tail;
-static size_t log_tail_next;
-
-/* Size of one FIFO entry */
-#define ENTRY_SIZE(payload_sz) (1+DIV_ROUND_UP((payload_sz), UNIT_SIZE))
-
-void log_add_event(uint8_t type, uint8_t size, uint16_t data,
- void *payload, uint32_t timestamp)
-{
- struct event_log_entry *r;
- size_t payload_size = EVENT_LOG_SIZE(size);
- size_t total_size = ENTRY_SIZE(payload_size);
- size_t current_tail, first;
- uint32_t lock_key;
-
- /* --- critical section : reserve queue space --- */
- lock_key = irq_lock();
- current_tail = log_tail_next;
- log_tail_next = current_tail + total_size;
- irq_unlock(lock_key);
- /* --- end of critical section --- */
-
- /* Out of space : discard the oldest entry */
- while ((UNIT_COUNT - (current_tail - log_head)) < total_size) {
- struct event_log_entry *oldest;
- /* --- critical section : atomically free-up space --- */
- lock_key = irq_lock();
- oldest = log_events + (log_head & UNIT_COUNT_MASK);
- log_head += ENTRY_SIZE(EVENT_LOG_SIZE(oldest->size));
- irq_unlock(lock_key);
- /* --- end of critical section --- */
- }
-
- r = log_events + (current_tail & UNIT_COUNT_MASK);
-
- r->timestamp = timestamp;
- r->type = type;
- r->size = size;
- r->data = data;
- /* copy the payload into the FIFO */
- first = MIN(total_size - 1, (UNIT_COUNT -
- (current_tail & UNIT_COUNT_MASK)) - 1);
- if (first)
- memcpy(r->payload, payload, first * UNIT_SIZE);
- if (first < total_size - 1)
- memcpy(log_events, ((uint8_t *)payload) + first * UNIT_SIZE,
- (total_size - first) * UNIT_SIZE);
- /* mark the entry available in the queue if nobody is behind us */
- if (current_tail == log_tail)
- log_tail = log_tail_next;
-}
-
-int log_dequeue_event(struct event_log_entry *r)
-{
- uint32_t now = get_time().val >> EVENT_LOG_TIMESTAMP_SHIFT;
- unsigned int total_size, first;
- struct event_log_entry *entry;
- size_t current_head;
- uint32_t lock_key;
-
-retry:
- current_head = log_head;
- /* The log FIFO is empty */
- if (log_tail == current_head) {
- memset(r, 0, UNIT_SIZE);
- r->type = EVENT_LOG_NO_ENTRY;
- return UNIT_SIZE;
- }
-
- entry = log_events + (current_head & UNIT_COUNT_MASK);
- total_size = ENTRY_SIZE(EVENT_LOG_SIZE(entry->size));
- first = MIN(total_size, UNIT_COUNT - (current_head & UNIT_COUNT_MASK));
- memcpy(r, entry, first * UNIT_SIZE);
- if (first < total_size)
- memcpy(r + first, log_events, (total_size-first) * UNIT_SIZE);
-
- /* --- critical section : remove the entry from the queue --- */
- lock_key = irq_lock();
- if (log_head != current_head) { /* our entry was thrown away */
- irq_unlock(lock_key);
- goto retry;
- }
- log_head += total_size;
- irq_unlock(lock_key);
- /* --- end of critical section --- */
-
- /* fixup the timestamp : number of milliseconds in the past */
- r->timestamp = now - r->timestamp;
-
- return total_size * UNIT_SIZE;
-}
-
-#ifdef CONFIG_CMD_DLOG
-/*
- * Display TPM event logs.
- */
-static int command_dlog(int argc, char **argv)
-{
- size_t log_cur;
- const uint8_t * const log_events_end =
- (uint8_t *)&log_events[UNIT_COUNT];
-
- if (argc > 1) {
- if (!strcasecmp(argv[1], "clear")) {
- interrupt_disable();
- log_head = log_tail = log_tail_next = 0;
- interrupt_enable();
-
- return EC_SUCCESS;
- }
- /* Too many parameters */
- return EC_ERROR_PARAM1;
- }
-
- ccprintf(" TIMESTAMP | TYPE | DATA | SIZE | PAYLOAD\n");
- log_cur = log_head;
- while (log_cur != log_tail) {
- struct event_log_entry *r;
- uint8_t *payload;
- uint32_t payload_bytes;
-
- r = &log_events[log_cur & UNIT_COUNT_MASK];
- payload_bytes = EVENT_LOG_SIZE(r->size);
- log_cur += ENTRY_SIZE(payload_bytes);
-
- ccprintf("%10d %4d 0x%04X %4d ", r->timestamp, r->type,
- r->data, payload_bytes);
-
- /* display payload if exists */
- payload = r->payload;
- while (payload_bytes--) {
- if (payload >= log_events_end)
- payload = (uint8_t *)&log_events[0];
-
- ccprintf("%02X", *payload);
- payload++;
- }
- ccprintf("\n");
- }
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(dlog,
- command_dlog,
- "[clear]",
- "Display/clear TPM event logs");
-#endif
diff --git a/common/extpower_common.c b/common/extpower_common.c
deleted file mode 100644
index 9021b77626..0000000000
--- a/common/extpower_common.c
+++ /dev/null
@@ -1,29 +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.
- */
-
-#include "extpower.h"
-#include "hooks.h"
-#include "host_command.h"
-
-__overridable void board_check_extpower(void)
-{
-}
-
-void extpower_handle_update(int is_present)
-{
- uint8_t *memmap_batt_flags;
-
- hook_notify(HOOK_AC_CHANGE);
- memmap_batt_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG);
-
- /* Forward notification to host */
- if (is_present) {
- *memmap_batt_flags |= EC_BATT_FLAG_AC_PRESENT;
- host_set_single_event(EC_HOST_EVENT_AC_CONNECTED);
- } else {
- *memmap_batt_flags &= ~EC_BATT_FLAG_AC_PRESENT;
- host_set_single_event(EC_HOST_EVENT_AC_DISCONNECTED);
- }
-}
diff --git a/common/extpower_gpio.c b/common/extpower_gpio.c
deleted file mode 100644
index 4cdcb834f8..0000000000
--- a/common/extpower_gpio.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/* Copyright 2013 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.
- */
-
-/* Pure GPIO-based external power detection */
-
-#include "common.h"
-#include "extpower.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "timer.h"
-
-static int debounced_extpower_presence;
-
-int extpower_is_present(void)
-{
- return debounced_extpower_presence;
-}
-
-/**
- * Deferred function to handle external power change
- */
-static void extpower_deferred(void)
-{
- int extpower_presence = gpio_get_level(GPIO_AC_PRESENT);
-
- if (extpower_presence == debounced_extpower_presence)
- return;
-
- debounced_extpower_presence = extpower_presence;
- extpower_handle_update(extpower_presence);
-
-}
-DECLARE_DEFERRED(extpower_deferred);
-
-void extpower_interrupt(enum gpio_signal signal)
-{
- /* Trigger deferred notification of external power change */
- hook_call_deferred(&extpower_deferred_data,
- CONFIG_EXTPOWER_DEBOUNCE_MS * MSEC);
-}
-
-static void extpower_init(void)
-{
- uint8_t *memmap_batt_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG);
-
- debounced_extpower_presence = gpio_get_level(GPIO_AC_PRESENT);
-
- /* Initialize the memory-mapped AC_PRESENT flag */
- if (debounced_extpower_presence)
- *memmap_batt_flags |= EC_BATT_FLAG_AC_PRESENT;
- else
- *memmap_batt_flags &= ~EC_BATT_FLAG_AC_PRESENT;
-
- /* Enable interrupts, now that we've initialized */
- gpio_enable_interrupt(GPIO_AC_PRESENT);
-}
-DECLARE_HOOK(HOOK_INIT, extpower_init, HOOK_PRIO_INIT_EXTPOWER);
diff --git a/common/fan.c b/common/fan.c
deleted file mode 100644
index 636bec04f9..0000000000
--- a/common/fan.c
+++ /dev/null
@@ -1,622 +0,0 @@
-/* Copyright 2013 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.
- */
-
-/* Basic Chrome OS fan control */
-
-#include "assert.h"
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "fan.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "printf.h"
-#include "system.h"
-#include "util.h"
-
-/* True if we're listening to the thermal control task. False if we're setting
- * things manually. */
-static int thermal_control_enabled[CONFIG_FANS];
-
-int is_thermal_control_enabled(int idx)
-{
- return thermal_control_enabled[idx];
-}
-
-#ifdef CONFIG_FAN_UPDATE_PERIOD
-/* Should we ignore the fans for a while? */
-static int fan_update_counter[CONFIG_FANS];
-#endif
-
-/*
- * Number of fans.
- *
- * Use fan_get_count and fan_set_count to access it. It should be set only
- * before HOOK_INIT/HOOK_PRIO_DEFAULT.
- */
-static int fan_count = CONFIG_FANS;
-
-int fan_get_count(void)
-{
- return fan_count;
-}
-
-void fan_set_count(int count)
-{
- /* You can only decrease the count. */
- assert(count <= CONFIG_FANS);
- fan_count = count;
-}
-
-#ifndef CONFIG_FAN_RPM_CUSTOM
-/* This is the default implementation. It's only called over [0,100].
- * Convert the percentage to a target RPM. We can't simply scale all
- * the way down to zero because most fans won't turn that slowly, so
- * we'll map [1,100] => [FAN_MIN,FAN_MAX], and [0] => "off".
-*/
-int fan_percent_to_rpm(int fan, int pct)
-{
- int rpm, max, min;
-
- if (!pct) {
- rpm = 0;
- } else {
- min = fans[fan].rpm->rpm_min;
- max = fans[fan].rpm->rpm_max;
- rpm = ((pct - 1) * max + (100 - pct) * min) / 99;
- }
-
- return rpm;
-}
-#endif /* CONFIG_FAN_RPM_CUSTOM */
-
-/* The thermal task will only call this function with pct in [0,100]. */
-test_mockable void fan_set_percent_needed(int fan, int pct)
-{
- int actual_rpm, new_rpm;
-
- if (!is_thermal_control_enabled(fan))
- return;
-
-#ifdef CONFIG_FAN_UPDATE_PERIOD
- /* Only set each fan every so often, to avoid rapid changes. */
- fan_update_counter[fan] %= CONFIG_FAN_UPDATE_PERIOD;
- if (fan_update_counter[fan]++)
- return;
-#endif
-
- new_rpm = fan_percent_to_rpm(fan, pct);
- actual_rpm = fan_get_rpm_actual(FAN_CH(fan));
-
- /* If we want to turn and the fans are currently significantly below
- * the minimum turning speed, we should turn at least as fast as the
- * necessary start speed instead. */
- if (new_rpm &&
- actual_rpm < fans[fan].rpm->rpm_min * 9 / 10 &&
- new_rpm < fans[fan].rpm->rpm_start)
- new_rpm = fans[fan].rpm->rpm_start;
-
- fan_set_rpm_target(FAN_CH(fan), new_rpm);
-}
-
-static void set_enabled(int fan, int enable)
-{
- fan_set_enabled(FAN_CH(fan), enable);
-
- if (fans[fan].conf->enable_gpio >= 0)
- gpio_set_level(fans[fan].conf->enable_gpio, enable);
-}
-
-test_export_static void set_thermal_control_enabled(int fan, int enable)
-{
- thermal_control_enabled[fan] = enable;
-
- /* If controlling the fan, need it in RPM-control mode */
- if (enable)
- fan_set_rpm_mode(FAN_CH(fan), 1);
-}
-
-static void set_duty_cycle(int fan, int percent)
-{
- /* Move the fan to manual control */
- fan_set_rpm_mode(FAN_CH(fan), 0);
-
- /* enable the fan when non-zero duty */
- set_enabled(fan, (percent > 0) ? 1 : 0);
-
- /* Disable thermal engine automatic fan control. */
- set_thermal_control_enabled(fan, 0);
-
- /* Set the duty cycle */
- fan_set_duty(FAN_CH(fan), percent);
-}
-
-/*****************************************************************************/
-/* Console commands */
-
-static int cc_fanauto(int argc, char **argv)
-{
- char *e;
- int fan = 0;
-
- if (fan_count > 1) {
- if (argc < 2) {
- ccprintf("fan number is required as the first arg\n");
- return EC_ERROR_PARAM_COUNT;
- }
- fan = strtoi(argv[1], &e, 0);
- if (*e || fan >= fan_count)
- return EC_ERROR_PARAM1;
- argc--;
- argv++;
- }
-
- set_thermal_control_enabled(fan, 1);
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(fanauto, cc_fanauto,
- "{fan}",
- "Enable thermal fan control");
-
-/* Return 0 for off, 1 for on, -1 for unknown */
-static int is_powered(int fan)
-{
- int is_pgood = -1;
-
- /* If we have an enable output, see if it's on or off. */
- if (fans[fan].conf->enable_gpio >= 0)
- is_pgood = gpio_get_level(fans[fan].conf->enable_gpio);
- /* If we have a pgood input, it overrides any enable output. */
- if (fans[fan].conf->pgood_gpio >= 0)
- is_pgood = gpio_get_level(fans[fan].conf->pgood_gpio);
-
- return is_pgood;
-}
-
-static int cc_faninfo(int argc, char **argv)
-{
- static const char * const human_status[] = {
- "not spinning", "changing", "locked", "frustrated"
- };
- int tmp, is_pgood;
- int fan;
- char leader[20] = "";
- for (fan = 0; fan < fan_count; fan++) {
- if (fan_count > 1)
- snprintf(leader, sizeof(leader), "Fan %d ", fan);
- if (fan)
- ccprintf("\n");
- ccprintf("%sActual: %4d rpm\n", leader,
- fan_get_rpm_actual(FAN_CH(fan)));
- ccprintf("%sTarget: %4d rpm\n", leader,
- fan_get_rpm_target(FAN_CH(fan)));
- ccprintf("%sDuty: %d%%\n", leader,
- fan_get_duty(FAN_CH(fan)));
- tmp = fan_get_status(FAN_CH(fan));
- ccprintf("%sStatus: %d (%s)\n", leader,
- tmp, human_status[tmp]);
- ccprintf("%sMode: %s\n", leader,
- fan_get_rpm_mode(FAN_CH(fan)) ? "rpm" : "duty");
- ccprintf("%sAuto: %s\n", leader,
- is_thermal_control_enabled(fan) ? "yes" : "no");
- ccprintf("%sEnable: %s\n", leader,
- fan_get_enabled(FAN_CH(fan)) ? "yes" : "no");
- is_pgood = is_powered(fan);
- if (is_pgood >= 0)
- ccprintf("%sPower: %s\n", leader,
- is_pgood ? "yes" : "no");
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(faninfo, cc_faninfo,
- NULL,
- "Print fan info");
-
-static int cc_fanset(int argc, char **argv)
-{
- const char *rpm_str;
- int rpm;
- char *e;
- int fan = 0;
-
- if (fan_count == 0) {
- ccprintf("Fan count is zero\n");
- return EC_ERROR_INVAL;
- }
-
- if (fan_count > 1) {
- if (argc < 3) {
- ccprintf("fan number is required as the first arg\n");
- return EC_ERROR_PARAM_COUNT;
- }
- }
-
- if (argc == 3) {
- fan = strtoi(argv[1], &e, 0);
- if (*e || fan >= fan_count)
- return EC_ERROR_PARAM1;
- rpm_str = argv[2];
- } else if (argc == 2) {
- rpm_str = argv[1];
- } else {
- return EC_ERROR_PARAM_COUNT;
- }
-
- rpm = strtoi(rpm_str, &e, 0);
- if (*e == '%') { /* Wait, that's a percentage */
- ccprintf("Fan rpm given as %d%%\n", rpm);
- if (rpm < 0)
- rpm = 0;
- else if (rpm > 100)
- rpm = 100;
- rpm = fan_percent_to_rpm(fan, rpm);
- } else if (*e) {
- return EC_ERROR_PARAM1;
- }
-
- /* Move the fan to automatic control */
- fan_set_rpm_mode(FAN_CH(fan), 1);
-
- /* enable the fan when non-zero rpm */
- set_enabled(fan, (rpm > 0) ? 1 : 0);
-
- /* Disable thermal engine automatic fan control. */
- set_thermal_control_enabled(fan, 0);
-
- fan_set_rpm_target(FAN_CH(fan), rpm);
-
- ccprintf("Setting fan %d rpm target to %d\n", fan, rpm);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(fanset, cc_fanset,
- "[fan] (rpm | pct%)",
- "Set fan speed");
-
-static int cc_fanduty(int argc, char **argv)
-{
- const char *percent_str;
- int percent = 0;
- char *e;
- int fan = 0;
-
- if (fan_count == 0) {
- ccprintf("Fan count is zero\n");
- return EC_ERROR_INVAL;
- }
-
- if (fan_count > 1) {
- if (argc < 3) {
- ccprintf("fan number is required as the first arg\n");
- return EC_ERROR_PARAM_COUNT;
- }
- }
-
- if (argc == 3) {
- fan = strtoi(argv[1], &e, 0);
- if (*e || fan >= fan_count)
- return EC_ERROR_PARAM1;
- percent_str = argv[2];
- } else if (argc == 2) {
- percent_str = argv[1];
- } else {
- return EC_ERROR_PARAM_COUNT;
- }
-
- percent = strtoi(percent_str, &e, 0);
- if (*e)
- return EC_ERROR_PARAM1;
-
- ccprintf("Setting fan %d duty cycle to %d%%\n", fan, percent);
- set_duty_cycle(fan, percent);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(fanduty, cc_fanduty,
- "[fan] percent",
- "Set fan duty cycle");
-
-/*****************************************************************************/
-/* DPTF interface functions */
-
-/* 0-100% if in duty mode. -1 if not */
-int dptf_get_fan_duty_target(void)
-{
- int fan = 0; /* TODO(crosbug.com/p/23803) */
-
- if (fan_count == 0)
- return -1;
-
- if (is_thermal_control_enabled(fan) || fan_get_rpm_mode(FAN_CH(fan)))
- return -1;
-
- return fan_get_duty(FAN_CH(fan));
-}
-
-/* 0-100% sets duty, out of range means let the EC drive */
-void dptf_set_fan_duty_target(int pct)
-{
- int fan;
-
- if (pct < 0 || pct > 100) {
- /* TODO(crosbug.com/p/23803) */
- for (fan = 0; fan < fan_count; fan++)
- set_thermal_control_enabled(fan, 1);
- } else {
- /* TODO(crosbug.com/p/23803) */
- for (fan = 0; fan < fan_count; fan++)
- set_duty_cycle(fan, pct);
- }
-}
-
-/*****************************************************************************/
-/* Host commands */
-
-static enum ec_status
-hc_pwm_get_fan_target_rpm(struct host_cmd_handler_args *args)
-{
- struct ec_response_pwm_get_fan_rpm *r = args->response;
-
- if (fan_count == 0)
- return EC_RES_ERROR;
-
- /* TODO(crosbug.com/p/23803) */
- r->rpm = fan_get_rpm_target(FAN_CH(0));
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_FAN_TARGET_RPM,
- hc_pwm_get_fan_target_rpm,
- EC_VER_MASK(0));
-
-static enum ec_status
-hc_pwm_set_fan_target_rpm(struct host_cmd_handler_args *args)
-{
- const struct ec_params_pwm_set_fan_target_rpm_v1 *p_v1 = args->params;
- const struct ec_params_pwm_set_fan_target_rpm_v0 *p_v0 = args->params;
- int fan;
-
- if (args->version == 0) {
- for (fan = 0; fan < fan_count; fan++) {
- /* enable the fan if rpm is non-zero */
- set_enabled(fan, (p_v0->rpm > 0) ? 1 : 0);
-
- set_thermal_control_enabled(fan, 0);
- fan_set_rpm_mode(FAN_CH(fan), 1);
- fan_set_rpm_target(FAN_CH(fan), p_v0->rpm);
- }
-
- return EC_RES_SUCCESS;
- }
-
- fan = p_v1->fan_idx;
- if (fan >= fan_count)
- return EC_RES_ERROR;
-
- /* enable the fan if rpm is non-zero */
- set_enabled(fan, (p_v1->rpm > 0) ? 1 :0);
-
- set_thermal_control_enabled(fan, 0);
- fan_set_rpm_mode(FAN_CH(fan), 1);
- fan_set_rpm_target(FAN_CH(fan), p_v1->rpm);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_FAN_TARGET_RPM,
- hc_pwm_set_fan_target_rpm,
- EC_VER_MASK(0) | EC_VER_MASK(1));
-
-static enum ec_status hc_pwm_set_fan_duty(struct host_cmd_handler_args *args)
-{
- const struct ec_params_pwm_set_fan_duty_v1 *p_v1 = args->params;
- const struct ec_params_pwm_set_fan_duty_v0 *p_v0 = args->params;
- int fan;
-
- if (args->version == 0) {
- for (fan = 0; fan < fan_count; fan++)
- set_duty_cycle(fan, p_v0->percent);
-
- return EC_RES_SUCCESS;
- }
-
- fan = p_v1->fan_idx;
- if (fan >= fan_count)
- return EC_RES_ERROR;
-
- set_duty_cycle(fan, p_v1->percent);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_FAN_DUTY,
- hc_pwm_set_fan_duty,
- EC_VER_MASK(0) | EC_VER_MASK(1));
-
-static enum ec_status
-hc_thermal_auto_fan_ctrl(struct host_cmd_handler_args *args)
-{
- int fan;
- const struct ec_params_auto_fan_ctrl_v1 *p_v1 = args->params;
-
- if (args->version == 0) {
- for (fan = 0; fan < fan_count; fan++)
- set_thermal_control_enabled(fan, 1);
-
- return EC_RES_SUCCESS;
- }
-
- fan = p_v1->fan_idx;
- if (fan >= fan_count)
- return EC_RES_ERROR;
-
- set_thermal_control_enabled(fan, 1);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_THERMAL_AUTO_FAN_CTRL,
- hc_thermal_auto_fan_ctrl,
- EC_VER_MASK(0)|EC_VER_MASK(1));
-
-
-/*****************************************************************************/
-/* Hooks */
-
-/* We only have a limited number of memory-mapped slots to report fan speed to
- * the AP. If we have more fans than that, some will be inaccessible. But
- * if we're using that many fans, we probably have bigger problems.
- */
-BUILD_ASSERT(CONFIG_FANS <= EC_FAN_SPEED_ENTRIES);
-
-#define PWMFAN_SYSJUMP_TAG 0x5046 /* "PF" */
-#define PWM_HOOK_VERSION 1
-/* Saved PWM state across sysjumps */
-struct pwm_fan_state {
- /* TODO(crosbug.com/p/23530): Still treating all fans as one. */
- uint16_t rpm;
- uint8_t flag; /* FAN_STATE_FLAG_* */
-};
-
-/* For struct pwm_fan_state.flag */
-#define FAN_STATE_FLAG_ENABLED BIT(0)
-#define FAN_STATE_FLAG_THERMAL BIT(1)
-
-static void pwm_fan_init(void)
-{
- const struct pwm_fan_state *prev;
- struct pwm_fan_state state;
- uint16_t *mapped;
- int version, size;
- int i;
- int fan;
-
- if (fan_count == 0)
- return;
-
- for (fan = 0; fan < fan_count; fan++)
- fan_channel_setup(FAN_CH(fan), fans[fan].conf->flags);
-
- /* Restore previous state. */
- prev = (const struct pwm_fan_state *)
- system_get_jump_tag(PWMFAN_SYSJUMP_TAG, &version, &size);
- if (prev && version == PWM_HOOK_VERSION && size == sizeof(*prev)) {
- memcpy(&state, prev, sizeof(state));
- } else {
- memset(&state, 0, sizeof(state));
- }
-
- for (fan = 0; fan < fan_count; fan++) {
- fan_set_enabled(FAN_CH(fan),
- state.flag & FAN_STATE_FLAG_ENABLED);
- fan_set_rpm_target(FAN_CH(fan), state.rpm);
- set_thermal_control_enabled(
- fan, state.flag & FAN_STATE_FLAG_THERMAL);
- }
-
- /* Initialize memory-mapped data */
- mapped = (uint16_t *)host_get_memmap(EC_MEMMAP_FAN);
- for (i = 0; i < EC_FAN_SPEED_ENTRIES; i++)
- mapped[i] = EC_FAN_SPEED_NOT_PRESENT;
-}
-DECLARE_HOOK(HOOK_INIT, pwm_fan_init, HOOK_PRIO_DEFAULT);
-
-static void pwm_fan_second(void)
-{
- uint16_t *mapped = (uint16_t *)host_get_memmap(EC_MEMMAP_FAN);
- uint16_t rpm;
- int stalled = 0;
- int fan;
-
- for (fan = 0; fan < fan_count; fan++) {
- if (fan_is_stalled(FAN_CH(fan))) {
- rpm = EC_FAN_SPEED_STALLED;
- stalled = 1;
- cprints(CC_PWM, "Fan %d stalled!", fan);
- } else {
- rpm = fan_get_rpm_actual(FAN_CH(fan));
- }
-
- mapped[fan] = rpm;
- }
-
- /*
- * Issue warning. As we have thermal shutdown
- * protection, issuing warning here should be enough.
- */
- if (stalled)
- host_set_single_event(EC_HOST_EVENT_THERMAL);
-}
-DECLARE_HOOK(HOOK_SECOND, pwm_fan_second, HOOK_PRIO_DEFAULT);
-
-static void pwm_fan_preserve_state(void)
-{
- struct pwm_fan_state state = {0};
- int fan = 0;
-
- if (fan_count == 0)
- return;
-
- /* TODO(crosbug.com/p/23530): Still treating all fans as one. */
- if (fan_get_enabled(FAN_CH(fan)))
- state.flag |= FAN_STATE_FLAG_ENABLED;
- if (is_thermal_control_enabled(fan))
- state.flag |= FAN_STATE_FLAG_THERMAL;
- state.rpm = fan_get_rpm_target(FAN_CH(fan));
-
- system_add_jump_tag(PWMFAN_SYSJUMP_TAG, PWM_HOOK_VERSION,
- sizeof(state), &state);
-}
-DECLARE_HOOK(HOOK_SYSJUMP, pwm_fan_preserve_state, HOOK_PRIO_DEFAULT);
-
-static void pwm_fan_control(int enable)
-{
- int fan;
-
- /* TODO(crosbug.com/p/23530): Still treating all fans as one. */
- for (fan = 0; fan < fan_count; fan++) {
- set_thermal_control_enabled(fan, enable);
- fan_set_rpm_target(FAN_CH(fan), enable ?
- fan_percent_to_rpm(FAN_CH(fan), CONFIG_FAN_INIT_SPEED) :
- 0);
- set_enabled(fan, enable);
- }
-}
-
-static void pwm_fan_stop(void)
-{
- /*
- * There is no need to cool CPU in S3 or S5. We currently don't
- * have fans for battery or charger chip. Battery systems will
- * control charge current based on its own temperature readings.
- * Thus, we do not need to keep fans running in S3 or S5.
- *
- * Even with a fan on charging system, it's questionable to run
- * a fan in S3/S5. Under an extreme heat condition, spinning a
- * fan would create more heat as it draws current from a
- * battery and heat would come from ambient air instead of CPU.
- *
- * Thermal control may be already disabled if DPTF is used.
- */
- pwm_fan_control(0); /* crosbug.com/p/8097 */
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, pwm_fan_stop, HOOK_PRIO_DEFAULT);
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pwm_fan_stop, HOOK_PRIO_DEFAULT);
-
-static void pwm_fan_start(void)
-{
- /*
- * Even if the DPTF is enabled, enable thermal control here.
- * Upon booting to S0, if needed AP will disable/throttle it using
- * host commands.
- */
- if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ON))
- pwm_fan_control(1);
-}
-/* On Fizz, CHIPSET_RESUME isn't triggered when AP warm resets.
- * So we hook CHIPSET_RESET instead.
- */
-DECLARE_HOOK(HOOK_CHIPSET_RESET, pwm_fan_start, HOOK_PRIO_FIRST);
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, pwm_fan_start, HOOK_PRIO_DEFAULT);
diff --git a/common/flash.c b/common/flash.c
deleted file mode 100644
index c8f58a82af..0000000000
--- a/common/flash.c
+++ /dev/null
@@ -1,1562 +0,0 @@
-/* Copyright 2012 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.
- */
-
-/* Flash memory module for Chrome EC - common functions */
-
-#include "common.h"
-#include "console.h"
-#include "cros_board_info.h"
-#include "flash.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "otp.h"
-#include "rwsig.h"
-#include "shared_mem.h"
-#include "system.h"
-#include "util.h"
-#include "vboot_hash.h"
-
-/*
- * Contents of erased flash, as a 32-bit value. Most platforms erase flash
- * bits to 1.
- */
-#ifndef CONFIG_FLASH_ERASED_VALUE32
-#define CONFIG_FLASH_ERASED_VALUE32 (-1U)
-#endif
-
-#ifdef CONFIG_FLASH_PSTATE
-
-/*
- * If flash isn't mapped to the EC's address space, it's probably SPI, and
- * should be using SPI write protect, not PSTATE.
- */
-#if !defined(CONFIG_INTERNAL_STORAGE) || !defined(CONFIG_MAPPED_STORAGE)
-#error "PSTATE should only be used with internal mem-mapped flash."
-#endif
-
-#ifdef CONFIG_FLASH_PSTATE_BANK
-/* Persistent protection state - emulates a SPI status register for flashrom */
-/* NOTE: It's not expected that RO and RW will support
- * differing PSTATE versions. */
-#define PERSIST_STATE_VERSION 3 /* Expected persist_state.version */
-
-/* Flags for persist_state.flags */
-/* Protect persist state and RO firmware at boot */
-#define PERSIST_FLAG_PROTECT_RO 0x02
-#define PSTATE_VALID_FLAGS BIT(0)
-#define PSTATE_VALID_SERIALNO BIT(1)
-#define PSTATE_VALID_MAC_ADDR BIT(2)
-
-struct persist_state {
- uint8_t version; /* Version of this struct */
- uint8_t flags; /* Lock flags (PERSIST_FLAG_*) */
- uint8_t valid_fields; /* Flags for valid data. */
- uint8_t reserved; /* Reserved; set 0 */
-#ifdef CONFIG_SERIALNO_LEN
- uint8_t serialno[CONFIG_SERIALNO_LEN]; /* Serial number. */
-#endif /* CONFIG_SERIALNO_LEN */
-#ifdef CONFIG_MAC_ADDR_LEN
- uint8_t mac_addr[CONFIG_MAC_ADDR_LEN];
-#endif /* CONFIG_MAC_ADDR_LEN */
-#if !defined(CONFIG_SERIALNO_LEN) && !defined(CONFIG_MAC_ADDR_LEN)
- uint8_t padding[4 % CONFIG_FLASH_WRITE_SIZE];
-#endif
-};
-
-/* written with flash_physical_write, need to respect alignment constraints */
-#ifndef CHIP_FAMILY_STM32L /* STM32L1xx is somewhat lying to us */
-BUILD_ASSERT(sizeof(struct persist_state) % CONFIG_FLASH_WRITE_SIZE == 0);
-#endif
-
-BUILD_ASSERT(sizeof(struct persist_state) <= CONFIG_FW_PSTATE_SIZE);
-
-#else /* !CONFIG_FLASH_PSTATE_BANK */
-
-/*
- * Flags for write protect state depend on the erased value of flash. The
- * locked value must be the same as the unlocked value with one or more bits
- * transitioned away from the erased state. That way, it is possible to
- * rewrite the data in-place to set the lock.
- *
- * STM32F0x can only write 0x0000 to a non-erased half-word, which means
- * PSTATE_MAGIC_LOCKED isn't quite as pretty. That's ok; the only thing
- * we actually need to detect is PSTATE_MAGIC_UNLOCKED, since that's the
- * only value we'll ever alter, and the only value which causes us not to
- * lock the flash at boot.
- */
-#if (CONFIG_FLASH_ERASED_VALUE32 == -1U)
-#define PSTATE_MAGIC_UNLOCKED 0x4f4e5057 /* "WPNO" */
-#define PSTATE_MAGIC_LOCKED 0x00000000 /* "" */
-#elif (CONFIG_FLASH_ERASED_VALUE32 == 0)
-#define PSTATE_MAGIC_UNLOCKED 0x4f4e5057 /* "WPNO" */
-#define PSTATE_MAGIC_LOCKED 0x5f5f5057 /* "WP__" */
-#else
-/* What kind of wacky flash doesn't erase all bits to 1 or 0? */
-#error "PSTATE needs magic values for this flash architecture."
-#endif
-
-/*
- * Rewriting the write protect flag in place currently requires a minimum write
- * size <= the size of the flag value.
- *
- * We could work around this on chips with larger minimum write size by reading
- * the write block containing the flag into RAM, changing it to the locked
- * value, and then rewriting that block. But we should only pay for that
- * complexity when we run across another chip which needs it.
- */
-#if (CONFIG_FLASH_WRITE_SIZE > 4)
-#error "Non-bank-based PSTATE requires flash write size <= 32 bits."
-#endif
-
-const uint32_t pstate_data __attribute__((section(".rodata.pstate"))) =
-#ifdef CONFIG_FLASH_PSTATE_LOCKED
- PSTATE_MAGIC_LOCKED;
-#else
- PSTATE_MAGIC_UNLOCKED;
-#endif
-
-#endif /* !CONFIG_FLASH_PSTATE_BANK */
-#endif /* CONFIG_FLASH_PSTATE */
-
-#ifdef CONFIG_FLASH_MULTIPLE_REGION
-const struct ec_flash_bank *flash_bank_info(int bank)
-{
- int i;
- for (i = 0; i < ARRAY_SIZE(flash_bank_array); i++) {
- if (bank < flash_bank_array[i].count)
- return &flash_bank_array[i];
- bank -= flash_bank_array[i].count;
- }
-
- return NULL;
-}
-
-int crec_flash_bank_size(int bank)
-{
- int rv;
- const struct ec_flash_bank *info = flash_bank_info(bank);
-
- if (!info)
- return -1;
-
- rv = BIT(info->size_exp);
- ASSERT(rv > 0);
- return rv;
-}
-
-int crec_flash_bank_erase_size(int bank)
-{
- int rv;
- const struct ec_flash_bank *info = flash_bank_info(bank);
-
- if (!info)
- return -1;
-
- rv = BIT(info->erase_size_exp);
- ASSERT(rv > 0);
- return rv;
-}
-
-int crec_flash_bank_index(int offset)
-{
- int bank_offset = 0, i;
-
- if (offset == 0)
- return bank_offset;
-
- for (i = 0; i < ARRAY_SIZE(flash_bank_array); i++) {
- int all_sector_size = flash_bank_array[i].count <<
- flash_bank_array[i].size_exp;
- if (offset >= all_sector_size) {
- offset -= all_sector_size;
- bank_offset += flash_bank_array[i].count;
- continue;
- }
- if (offset & ((1 << flash_bank_array[i].size_exp) - 1))
- return -1;
- return bank_offset + (offset >> flash_bank_array[i].size_exp);
- }
- if (offset != 0)
- return -1;
- return bank_offset;
-}
-
-int crec_flash_bank_count(int offset, int size)
-{
- int begin = crec_flash_bank_index(offset);
- int end = crec_flash_bank_index(offset + size);
-
- if (begin == -1 || end == -1)
- return -1;
- return end - begin;
-}
-
-int crec_flash_bank_start_offset(int bank)
-{
- int i;
- int offset;
- int bank_size;
-
- if (bank < 0)
- return -1;
-
- offset = 0;
- for (i = 0; i < bank; i++) {
- bank_size = crec_flash_bank_size(i);
- if (bank_size < 0)
- return -1;
- offset += bank_size;
- }
-
- return offset;
-}
-
-#endif /* CONFIG_FLASH_MULTIPLE_REGION */
-
-static int flash_range_ok(int offset, int size_req, int align)
-{
- if (offset < 0 || size_req < 0 ||
- offset > CONFIG_FLASH_SIZE_BYTES ||
- size_req > CONFIG_FLASH_SIZE_BYTES ||
- offset + size_req > CONFIG_FLASH_SIZE_BYTES ||
- (offset | size_req) & (align - 1))
- return 0; /* Invalid range */
-
- return 1;
-}
-
-#ifdef CONFIG_MAPPED_STORAGE
-/**
- * Get the physical memory address of a flash offset
- *
- * This is used for direct flash access. We assume that the flash is
- * contiguous from this start address through to the end of the usable
- * flash.
- *
- * @param offset Flash offset to get address of
- * @param dataptrp Returns pointer to memory address of flash offset
- * @return pointer to flash memory offset, if ok, else NULL
- */
-static const char *flash_physical_dataptr(int offset)
-{
- return (char *)((uintptr_t)CONFIG_MAPPED_STORAGE_BASE + offset);
-}
-
-int crec_flash_dataptr(int offset, int size_req, int align, const char **ptrp)
-{
- if (!flash_range_ok(offset, size_req, align))
- return -1; /* Invalid range */
- if (ptrp)
- *ptrp = flash_physical_dataptr(offset);
-
- return CONFIG_FLASH_SIZE_BYTES - offset;
-}
-#endif
-
-#ifdef CONFIG_FLASH_PSTATE
-#ifdef CONFIG_FLASH_PSTATE_BANK
-
-/**
- * Read and return persistent state flags (EC_FLASH_PROTECT_*)
- */
-static uint32_t flash_read_pstate(void)
-{
- const struct persist_state *pstate =
- (const struct persist_state *)
- flash_physical_dataptr(CONFIG_FW_PSTATE_OFF);
-
- if ((pstate->version == PERSIST_STATE_VERSION) &&
- (pstate->valid_fields & PSTATE_VALID_FLAGS) &&
- (pstate->flags & PERSIST_FLAG_PROTECT_RO)) {
- /* Lock flag is known to be set */
- return EC_FLASH_PROTECT_RO_AT_BOOT;
- } else {
-#ifdef CONFIG_WP_ALWAYS
- return PERSIST_FLAG_PROTECT_RO;
-#else
- return 0;
-#endif
- }
-}
-
-/**
- * Write persistent state after erasing.
- *
- * @param pstate New data to set in pstate. NOT memory mapped
- * old pstate as it will be erased.
- * @return EC_SUCCESS, or nonzero if error.
- */
-static int flash_write_pstate_data(struct persist_state *newpstate)
-{
- int rv;
-
- /* Erase pstate */
- rv = crec_flash_physical_erase(CONFIG_FW_PSTATE_OFF,
- CONFIG_FW_PSTATE_SIZE);
- if (rv)
- return rv;
-
- /*
- * Note that if we lose power in here, we'll lose the pstate contents.
- * That's ok, because it's only possible to write the pstate before
- * it's protected.
- */
-
- /* Write the updated pstate */
- return crec_flash_physical_write(CONFIG_FW_PSTATE_OFF,
- sizeof(*newpstate),
- (const char *)newpstate);
-}
-
-
-
-/**
- * Validate and Init persistent state datastructure.
- *
- * @param pstate A pstate data structure. Will be valid at complete.
- * @return EC_SUCCESS, or nonzero if error.
- */
-static int validate_pstate_struct(struct persist_state *pstate)
-{
- if (pstate->version != PERSIST_STATE_VERSION) {
- memset(pstate, 0, sizeof(*pstate));
- pstate->version = PERSIST_STATE_VERSION;
- }
-
- return EC_SUCCESS;
-}
-
-/**
- * Write persistent state from pstate, erasing if necessary.
- *
- * @param flags New flash write protect flags to set in pstate.
- * @return EC_SUCCESS, or nonzero if error.
- */
-static int flash_write_pstate(uint32_t flags)
-{
- struct persist_state newpstate;
- const struct persist_state *pstate =
- (const struct persist_state *)
- flash_physical_dataptr(CONFIG_FW_PSTATE_OFF);
-
- /* Only check the flags we write to pstate */
- flags &= EC_FLASH_PROTECT_RO_AT_BOOT;
-
- /* Check if pstate has actually changed */
- if (flags == flash_read_pstate())
- return EC_SUCCESS;
-
- /* Cache the old copy for read/modify/write. */
- memcpy(&newpstate, pstate, sizeof(newpstate));
- validate_pstate_struct(&newpstate);
-
- if (flags & EC_FLASH_PROTECT_RO_AT_BOOT)
- newpstate.flags |= PERSIST_FLAG_PROTECT_RO;
- else
- newpstate.flags &= ~PERSIST_FLAG_PROTECT_RO;
- newpstate.valid_fields |= PSTATE_VALID_FLAGS;
-
- return flash_write_pstate_data(&newpstate);
-}
-
-#ifdef CONFIG_SERIALNO_LEN
-/**
- * Read and return persistent serial number.
- */
-const char *crec_flash_read_pstate_serial(void)
-{
- const struct persist_state *pstate =
- (const struct persist_state *)
- flash_physical_dataptr(CONFIG_FW_PSTATE_OFF);
-
- if ((pstate->version == PERSIST_STATE_VERSION) &&
- (pstate->valid_fields & PSTATE_VALID_SERIALNO)) {
- return (const char *)(pstate->serialno);
- }
-
- return NULL;
-}
-
-/**
- * Write persistent serial number to pstate, erasing if necessary.
- *
- * @param serialno New ascii serial number to set in pstate.
- * @return EC_SUCCESS, or nonzero if error.
- */
-int crec_flash_write_pstate_serial(const char *serialno)
-{
- int length;
- struct persist_state newpstate;
- const struct persist_state *pstate =
- (const struct persist_state *)
- flash_physical_dataptr(CONFIG_FW_PSTATE_OFF);
-
- /* Check that this is OK */
- if (!serialno)
- return EC_ERROR_INVAL;
-
- length = strnlen(serialno, sizeof(newpstate.serialno));
- if (length >= sizeof(newpstate.serialno)) {
- return EC_ERROR_INVAL;
- }
-
- /* Cache the old copy for read/modify/write. */
- memcpy(&newpstate, pstate, sizeof(newpstate));
- validate_pstate_struct(&newpstate);
-
- /*
- * Erase any prior data and copy the string. The length was verified to
- * be shorter than the buffer so a null terminator always remains.
- */
- memset(newpstate.serialno, '\0', sizeof(newpstate.serialno));
- memcpy(newpstate.serialno, serialno, length);
-
- newpstate.valid_fields |= PSTATE_VALID_SERIALNO;
-
- return flash_write_pstate_data(&newpstate);
-}
-
-#endif /* CONFIG_SERIALNO_LEN */
-
-#ifdef CONFIG_MAC_ADDR_LEN
-
-/**
- * Read and return persistent MAC address.
- */
-const char *crec_flash_read_pstate_mac_addr(void)
-{
- const struct persist_state *pstate =
- (const struct persist_state *)
- flash_physical_dataptr(CONFIG_FW_PSTATE_OFF);
-
- if ((pstate->version == PERSIST_STATE_VERSION) &&
- (pstate->valid_fields & PSTATE_VALID_MAC_ADDR)) {
- return (const char *)(pstate->mac_addr);
- }
-
- return NULL;
-}
-
-/**
- * Write persistent MAC Addr to pstate, erasing if necessary.
- *
- * @param mac_addr New ascii MAC address to set in pstate.
- * @return EC_SUCCESS, or nonzero if error.
- */
-int crec_flash_write_pstate_mac_addr(const char *mac_addr)
-{
- int length;
- struct persist_state newpstate;
- const struct persist_state *pstate =
- (const struct persist_state *)
- flash_physical_dataptr(CONFIG_FW_PSTATE_OFF);
-
- /* Check that this is OK, data is valid and fits in the region. */
- if (!mac_addr) {
- return EC_ERROR_INVAL;
- }
-
- /*
- * This will perform validation of the mac address before storing it.
- * The MAC address format is '12:34:56:78:90:AB', a 17 character long
- * string containing pairs of hex digits, each pair delimited by a ':'.
- */
- length = strnlen(mac_addr, sizeof(newpstate.mac_addr));
- if (length != 17) {
- return EC_ERROR_INVAL;
- }
- for (int i = 0; i < 17; i++) {
- if (i % 3 != 2) {
- /* Verify the remaining characters are hex digits. */
- if ((mac_addr[i] < '0' || '9' < mac_addr[i]) &&
- (mac_addr[i] < 'A' || 'F' < mac_addr[i]) &&
- (mac_addr[i] < 'a' || 'f' < mac_addr[i])) {
- return EC_ERROR_INVAL;
- }
- } else {
- /* Every 3rd character is a ':' */
- if (mac_addr[i] != ':') {
- return EC_ERROR_INVAL;
- }
- }
- }
-
- /* Cache the old copy for read/modify/write. */
- memcpy(&newpstate, pstate, sizeof(newpstate));
- validate_pstate_struct(&newpstate);
-
- /*
- * Erase any prior data and copy the string. The length was verified to
- * be shorter than the buffer so a null terminator always remains.
- */
- memset(newpstate.mac_addr, '\0', sizeof(newpstate.mac_addr));
- memcpy(newpstate.mac_addr, mac_addr, length);
-
- newpstate.valid_fields |= PSTATE_VALID_MAC_ADDR;
-
- return flash_write_pstate_data(&newpstate);
-}
-
-#endif /* CONFIG_MAC_ADDR_LEN */
-
-#else /* !CONFIG_FLASH_PSTATE_BANK */
-
-/**
- * Return the address of the pstate data in EC-RO.
- */
-static const uintptr_t get_pstate_addr(void)
-{
- uintptr_t addr = (uintptr_t)&pstate_data;
-
- /* Always use the pstate data in RO, even if we're RW */
- if (system_is_in_rw())
- addr += CONFIG_RO_MEM_OFF - CONFIG_RW_MEM_OFF;
-
- return addr;
-}
-
-/**
- * Read and return persistent state flags (EC_FLASH_PROTECT_*)
- */
-static uint32_t flash_read_pstate(void)
-{
- /* Check for the unlocked magic value */
- if (*(const uint32_t *)get_pstate_addr() == PSTATE_MAGIC_UNLOCKED)
- return 0;
-
- /* Anything else is locked */
- return EC_FLASH_PROTECT_RO_AT_BOOT;
-}
-
-/**
- * Write persistent state from pstate, erasing if necessary.
- *
- * @param flags New flash write protect flags to set in pstate.
- * @return EC_SUCCESS, or nonzero if error.
- */
-static int flash_write_pstate(uint32_t flags)
-{
- const uint32_t new_pstate = PSTATE_MAGIC_LOCKED;
-
- /* Only check the flags we write to pstate */
- flags &= EC_FLASH_PROTECT_RO_AT_BOOT;
-
- /* Check if pstate has actually changed */
- if (flags == flash_read_pstate())
- return EC_SUCCESS;
-
- /* We can only set the protect flag, not clear it */
- if (!(flags & EC_FLASH_PROTECT_RO_AT_BOOT))
- return EC_ERROR_ACCESS_DENIED;
-
- /*
- * Write a new pstate. We can overwrite the existing value, because
- * we're only moving bits from the erased state to the unerased state.
- */
- return crec_flash_physical_write(get_pstate_addr() -
- CONFIG_PROGRAM_MEMORY_BASE,
- sizeof(new_pstate),
- (const char *)&new_pstate);
-}
-
-#endif /* !CONFIG_FLASH_PSTATE_BANK */
-#endif /* CONFIG_FLASH_PSTATE */
-
-int crec_flash_is_erased(uint32_t offset, int size)
-{
- const uint32_t *ptr;
-
-#ifdef CONFIG_MAPPED_STORAGE
- /* Use pointer directly to flash */
- if (crec_flash_dataptr(offset, size, sizeof(uint32_t),
- (const char **)&ptr) < 0)
- return 0;
-
- crec_flash_lock_mapped_storage(1);
- for (size /= sizeof(uint32_t); size > 0; size--, ptr++)
- if (*ptr != CONFIG_FLASH_ERASED_VALUE32) {
- crec_flash_lock_mapped_storage(0);
- return 0;
- }
-
- crec_flash_lock_mapped_storage(0);
-#else
- /* Read flash a chunk at a time */
- uint32_t buf[8];
- int bsize;
-
- while (size) {
- bsize = MIN(size, sizeof(buf));
-
- if (crec_flash_read(offset, bsize, (char *)buf))
- return 0;
-
- size -= bsize;
- offset += bsize;
-
- ptr = buf;
- for (bsize /= sizeof(uint32_t); bsize > 0; bsize--, ptr++)
- if (*ptr != CONFIG_FLASH_ERASED_VALUE32)
- return 0;
-
- }
-#endif
-
- return 1;
-}
-
-int crec_flash_read(int offset, int size, char *data)
-{
-#ifdef CONFIG_MAPPED_STORAGE
- const char *src;
-
- if (crec_flash_dataptr(offset, size, 1, &src) < 0)
- return EC_ERROR_INVAL;
-
- crec_flash_lock_mapped_storage(1);
- memcpy(data, src, size);
- crec_flash_lock_mapped_storage(0);
- return EC_SUCCESS;
-#else
- return crec_flash_physical_read(offset, size, data);
-#endif
-}
-
-static void flash_abort_or_invalidate_hash(int offset, int size)
-{
-#ifdef CONFIG_VBOOT_HASH
- if (vboot_hash_in_progress()) {
- /* Abort hash calculation when flash update is in progress. */
- vboot_hash_abort();
- return;
- }
-
-#ifdef CONFIG_EXTERNAL_STORAGE
- /*
- * If EC executes in RAM and is currently in RW, we keep the current
- * hash. On the next hash check, AP will catch hash mismatch between the
- * flash copy and the RAM copy, then take necessary actions.
- */
- if (system_is_in_rw())
- return;
-#endif
-
- /* If EC executes in place, we need to invalidate the cached hash. */
- vboot_hash_invalidate(offset, size);
-#endif
-
-#ifdef HAS_TASK_RWSIG
- /*
- * If RW flash has been written to, make sure we do not automatically
- * jump to RW after the timeout.
- */
- if ((offset >= CONFIG_RW_MEM_OFF &&
- offset < (CONFIG_RW_MEM_OFF + CONFIG_RW_SIZE)) ||
- ((offset + size) > CONFIG_RW_MEM_OFF &&
- (offset + size) <= (CONFIG_RW_MEM_OFF + CONFIG_RW_SIZE)) ||
- (offset < CONFIG_RW_MEM_OFF &&
- (offset + size) > (CONFIG_RW_MEM_OFF + CONFIG_RW_SIZE)))
- rwsig_abort();
-#endif
-}
-
-int crec_flash_write(int offset, int size, const char *data)
-{
- if (!flash_range_ok(offset, size, CONFIG_FLASH_WRITE_SIZE))
- return EC_ERROR_INVAL; /* Invalid range */
-
- flash_abort_or_invalidate_hash(offset, size);
-
- return crec_flash_physical_write(offset, size, data);
-}
-
-int crec_flash_erase(int offset, int size)
-{
-#ifndef CONFIG_FLASH_MULTIPLE_REGION
- if (!flash_range_ok(offset, size, CONFIG_FLASH_ERASE_SIZE))
- return EC_ERROR_INVAL; /* Invalid range */
-#endif
-
- flash_abort_or_invalidate_hash(offset, size);
-
- return crec_flash_physical_erase(offset, size);
-}
-
-int crec_flash_protect_at_boot(uint32_t new_flags)
-{
-#ifdef CONFIG_FLASH_PSTATE
- uint32_t new_pstate_flags = new_flags & EC_FLASH_PROTECT_RO_AT_BOOT;
-
- /* Read the current persist state from flash */
- if (flash_read_pstate() != new_pstate_flags) {
- /* Need to update pstate */
- int rv;
-
-#ifdef CONFIG_FLASH_PSTATE_BANK
- /* Fail if write protect block is already locked */
- if (crec_flash_physical_get_protect(PSTATE_BANK))
- return EC_ERROR_ACCESS_DENIED;
-#endif
-
- /* Write the desired flags */
- rv = flash_write_pstate(new_pstate_flags);
- if (rv)
- return rv;
- }
-
-#ifdef CONFIG_FLASH_PROTECT_NEXT_BOOT
- /*
- * Try updating at-boot protection state, if on a platform where write
- * protection only changes after a reboot. Otherwise we wouldn't
- * update it until after the next reboot, and we'd need to reboot
- * again. Ignore errors, because the protection registers might
- * already be locked this boot, and we'll still apply the correct state
- * again on the next boot.
- *
- * This assumes PSTATE immediately follows RO, which it does on
- * all STM32 platforms (which are the only ones with this config).
- */
- crec_flash_physical_protect_at_boot(new_flags);
-#endif
-
- return EC_SUCCESS;
-#else
- return crec_flash_physical_protect_at_boot(new_flags);
-#endif
-}
-
-uint32_t crec_flash_get_protect(void)
-{
- uint32_t flags = 0;
- int i;
- /* Region protection status */
- int not_protected[FLASH_REGION_COUNT] = {0};
-#ifdef CONFIG_ROLLBACK
- /* Flags that must be set to set ALL_NOW flag. */
- const uint32_t all_flags = EC_FLASH_PROTECT_RO_NOW |
- EC_FLASH_PROTECT_RW_NOW |
- EC_FLASH_PROTECT_ROLLBACK_NOW;
-#else
- const uint32_t all_flags = EC_FLASH_PROTECT_RO_NOW |
- EC_FLASH_PROTECT_RW_NOW;
-#endif
-
- /* Read write protect GPIO */
-#ifdef CONFIG_WP_ALWAYS
- flags |= EC_FLASH_PROTECT_GPIO_ASSERTED;
-#elif defined(CONFIG_WP_ACTIVE_HIGH)
- if (gpio_get_level(GPIO_WP))
- flags |= EC_FLASH_PROTECT_GPIO_ASSERTED;
-#else
- if (!gpio_get_level(GPIO_WP_L))
- flags |= EC_FLASH_PROTECT_GPIO_ASSERTED;
-#endif
-
-#ifdef CONFIG_FLASH_PSTATE
- /* Read persistent state of RO-at-boot flag */
- flags |= flash_read_pstate();
-#endif
-
- /* Scan flash protection */
- for (i = 0; i < PHYSICAL_BANKS; i++) {
- int is_ro = (i >= WP_BANK_OFFSET &&
- i < WP_BANK_OFFSET + WP_BANK_COUNT);
- enum flash_region region = is_ro ? FLASH_REGION_RO :
- FLASH_REGION_RW;
- int bank_flag = is_ro ? EC_FLASH_PROTECT_RO_NOW :
- EC_FLASH_PROTECT_RW_NOW;
-
-#ifdef CONFIG_ROLLBACK
- if (i >= ROLLBACK_BANK_OFFSET &&
- i < ROLLBACK_BANK_OFFSET + ROLLBACK_BANK_COUNT) {
- region = FLASH_REGION_ROLLBACK;
- bank_flag = EC_FLASH_PROTECT_ROLLBACK_NOW;
- }
-#endif
-
- if (crec_flash_physical_get_protect(i)) {
- /* At least one bank in the region is protected */
- flags |= bank_flag;
- if (not_protected[region])
- flags |= EC_FLASH_PROTECT_ERROR_INCONSISTENT;
- } else {
- /* At least one bank in the region is NOT protected */
- not_protected[region] = 1;
- if (flags & bank_flag)
- flags |= EC_FLASH_PROTECT_ERROR_INCONSISTENT;
- }
- }
-
- if ((flags & all_flags) == all_flags)
- flags |= EC_FLASH_PROTECT_ALL_NOW;
-
- /*
- * If the RW or ROLLBACK banks are protected but the RO banks aren't,
- * that's inconsistent.
- *
- * Note that we check this before adding in the physical flags below,
- * since some chips can also protect ALL_NOW for the current boot by
- * locking up the flash program-erase registers.
- */
- if ((flags & all_flags) && !(flags & EC_FLASH_PROTECT_RO_NOW))
- flags |= EC_FLASH_PROTECT_ERROR_INCONSISTENT;
-
-#ifndef CONFIG_FLASH_PROTECT_RW
- /* RW flag was used for intermediate computations, clear it now. */
- flags &= ~EC_FLASH_PROTECT_RW_NOW;
-#endif
-
- /* Add in flags from physical layer */
- return flags | crec_flash_physical_get_protect_flags();
-}
-
-/*
- * Request a flash protection flags change for |mask| flash protect flags
- * to |flags| state.
- *
- * Order of flag processing:
- * 1. Clear/Set RO_AT_BOOT + Clear *_AT_BOOT flags + Commit *_AT_BOOT flags.
- * 2. Return if RO_AT_BOOT and HW-WP are not asserted.
- * 3. Set remaining *_AT_BOOT flags + Commit *_AT_BOOT flags.
- * 4. Commit RO_NOW.
- * 5. Commit ALL_NOW.
- */
-int crec_flash_set_protect(uint32_t mask, uint32_t flags)
-{
- int retval = EC_SUCCESS;
- int rv;
- int old_flags_at_boot = crec_flash_get_protect() &
- (EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RW_AT_BOOT |
- EC_FLASH_PROTECT_ROLLBACK_AT_BOOT |
- EC_FLASH_PROTECT_ALL_AT_BOOT);
- int new_flags_at_boot = old_flags_at_boot;
-
- /* Sanitize input flags */
- flags = flags & mask;
-
- /*
- * Process flags we can set. Track the most recent error, but process
- * all flags before returning.
- */
-
- /*
- * AT_BOOT flags are trickier than NOW flags, as they can be set
- * when HW write protection is disabled and can be unset without
- * a reboot.
- *
- * If we are only setting/clearing RO_AT_BOOT, things are simple.
- * Setting ALL_AT_BOOT is processed only if HW write protection is
- * enabled and RO_AT_BOOT is set, so it's also simple.
- *
- * The most tricky one is when we want to clear ALL_AT_BOOT. We need
- * to determine whether to clear protection for the entire flash or
- * leave RO protected. There are two cases that we want to keep RO
- * protected:
- * A. RO_AT_BOOT was already set before flash_set_protect() is
- * called.
- * B. RO_AT_BOOT was not set, but it's requested to be set by
- * the caller of flash_set_protect().
- */
-
- /* 1.a - Clear RO_AT_BOOT. */
- new_flags_at_boot &= ~(mask & EC_FLASH_PROTECT_RO_AT_BOOT);
- /* 1.b - Set RO_AT_BOOT. */
- new_flags_at_boot |= flags & EC_FLASH_PROTECT_RO_AT_BOOT;
-
- /* 1.c - Clear ALL_AT_BOOT. */
- if ((mask & EC_FLASH_PROTECT_ALL_AT_BOOT) &&
- !(flags & EC_FLASH_PROTECT_ALL_AT_BOOT)) {
- new_flags_at_boot &= ~EC_FLASH_PROTECT_ALL_AT_BOOT;
- /* Must also clear RW/ROLLBACK. */
-#ifdef CONFIG_FLASH_PROTECT_RW
- new_flags_at_boot &= ~EC_FLASH_PROTECT_RW_AT_BOOT;
-#endif
-#ifdef CONFIG_ROLLBACK
- new_flags_at_boot &= ~EC_FLASH_PROTECT_ROLLBACK_AT_BOOT;
-#endif
- }
-
- /* 1.d - Clear RW_AT_BOOT. */
-#ifdef CONFIG_FLASH_PROTECT_RW
- if ((mask & EC_FLASH_PROTECT_RW_AT_BOOT) &&
- !(flags & EC_FLASH_PROTECT_RW_AT_BOOT)) {
- new_flags_at_boot &= ~EC_FLASH_PROTECT_RW_AT_BOOT;
- /* Must also clear ALL (otherwise nothing will happen). */
- new_flags_at_boot &= ~EC_FLASH_PROTECT_ALL_AT_BOOT;
- }
-#endif
-
- /* 1.e - Clear ROLLBACK_AT_BOOT. */
-#ifdef CONFIG_ROLLBACK
- if ((mask & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) &&
- !(flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT)) {
- new_flags_at_boot &= ~EC_FLASH_PROTECT_ROLLBACK_AT_BOOT;
- /* Must also remove ALL (otherwise nothing will happen). */
- new_flags_at_boot &= ~EC_FLASH_PROTECT_ALL_AT_BOOT;
- }
-#endif
-
- /* 1.f - Commit *_AT_BOOT "clears" (and RO "set" 1.b). */
- if (new_flags_at_boot != old_flags_at_boot) {
- rv = crec_flash_protect_at_boot(new_flags_at_boot);
- if (rv)
- retval = rv;
- old_flags_at_boot = new_flags_at_boot;
- }
-
- /* 2 - Return if RO_AT_BOOT and HW-WP are not asserted.
- *
- * All subsequent flags only work if write protect is enabled (that is,
- * hardware WP flag) *and* RO is protected at boot (software WP flag).
- */
- if ((~crec_flash_get_protect()) & (EC_FLASH_PROTECT_GPIO_ASSERTED |
- EC_FLASH_PROTECT_RO_AT_BOOT))
- return retval;
-
- /*
- * 3.a - Set ALL_AT_BOOT.
- *
- * The case where ALL/RW/ROLLBACK_AT_BOOT is cleared is already covered
- * above, so we do not need to mask it out.
- */
- new_flags_at_boot |= flags & EC_FLASH_PROTECT_ALL_AT_BOOT;
-
- /* 3.b - Set RW_AT_BOOT. */
-#ifdef CONFIG_FLASH_PROTECT_RW
- new_flags_at_boot |= flags & EC_FLASH_PROTECT_RW_AT_BOOT;
-#endif
-
- /* 3.c - Set ROLLBACK_AT_BOOT. */
-#ifdef CONFIG_ROLLBACK
- new_flags_at_boot |= flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT;
-#endif
-
- /* 3.d - Commit *_AT_BOOT "sets". */
- if (new_flags_at_boot != old_flags_at_boot) {
- rv = crec_flash_protect_at_boot(new_flags_at_boot);
- if (rv)
- retval = rv;
- }
-
- /* 4 - Commit RO_NOW. */
- if (flags & EC_FLASH_PROTECT_RO_NOW) {
- rv = crec_flash_physical_protect_now(0);
- if (rv)
- retval = rv;
-
- /*
- * Latch the CBI EEPROM WP immediately if HW WP is asserted and
- * we're now protecting the RO region with SW WP.
- */
- if (IS_ENABLED(CONFIG_EEPROM_CBI_WP) &&
- (EC_FLASH_PROTECT_GPIO_ASSERTED &
- crec_flash_get_protect()))
- cbi_latch_eeprom_wp();
- }
-
- /* 5 - Commit ALL_NOW. */
- if (flags & EC_FLASH_PROTECT_ALL_NOW) {
- rv = crec_flash_physical_protect_now(1);
- if (rv)
- retval = rv;
- }
-
- return retval;
-}
-
-#ifdef CONFIG_FLASH_DEFERRED_ERASE
-static volatile enum ec_status erase_rc = EC_RES_SUCCESS;
-static struct ec_params_flash_erase_v1 erase_info;
-
-static void flash_erase_deferred(void)
-{
- erase_rc = EC_RES_BUSY;
- if (crec_flash_erase(erase_info.params.offset, erase_info.params.size))
- erase_rc = EC_RES_ERROR;
- else
- erase_rc = EC_RES_SUCCESS;
-}
-DECLARE_DEFERRED(flash_erase_deferred);
-#endif
-
-/*****************************************************************************/
-/* Console commands */
-
-#ifdef CONFIG_CMD_FLASHINFO
-static int command_flash_info(int argc, char **argv)
-{
- int i, flags;
-
- ccprintf("Usable: %4d KB\n", CONFIG_FLASH_SIZE_BYTES / 1024);
- ccprintf("Write: %4d B (ideal %d B)\n", CONFIG_FLASH_WRITE_SIZE,
- CONFIG_FLASH_WRITE_IDEAL_SIZE);
-#ifdef CONFIG_FLASH_MULTIPLE_REGION
- ccprintf("Regions:\n");
- for (i = 0; i < ARRAY_SIZE(flash_bank_array); i++) {
- ccprintf(" %d region%s:\n",
- flash_bank_array[i].count,
- (flash_bank_array[i].count == 1 ? "" : "s"));
- ccprintf(" Erase: %4d B (to %d-bits)\n",
- 1 << flash_bank_array[i].erase_size_exp,
- CONFIG_FLASH_ERASED_VALUE32 ? 1 : 0);
- ccprintf(" Size/Protect: %4d B\n",
- 1 << flash_bank_array[i].size_exp);
- }
-#else
- ccprintf("Erase: %4d B (to %d-bits)\n", CONFIG_FLASH_ERASE_SIZE,
- CONFIG_FLASH_ERASED_VALUE32 ? 1 : 0);
- ccprintf("Protect: %4d B\n", CONFIG_FLASH_BANK_SIZE);
-#endif
- flags = crec_flash_get_protect();
- ccprintf("Flags: ");
- if (flags & EC_FLASH_PROTECT_GPIO_ASSERTED)
- ccputs(" wp_gpio_asserted");
- if (flags & EC_FLASH_PROTECT_RO_AT_BOOT)
- ccputs(" ro_at_boot");
- if (flags & EC_FLASH_PROTECT_ALL_AT_BOOT)
- ccputs(" all_at_boot");
- if (flags & EC_FLASH_PROTECT_RO_NOW)
- ccputs(" ro_now");
- if (flags & EC_FLASH_PROTECT_ALL_NOW)
- ccputs(" all_now");
-#ifdef CONFIG_FLASH_PROTECT_RW
- if (flags & EC_FLASH_PROTECT_RW_AT_BOOT)
- ccputs(" rw_at_boot");
- if (flags & EC_FLASH_PROTECT_RW_NOW)
- ccputs(" rw_now");
-#endif
- if (flags & EC_FLASH_PROTECT_ERROR_STUCK)
- ccputs(" STUCK");
- if (flags & EC_FLASH_PROTECT_ERROR_INCONSISTENT)
- ccputs(" INCONSISTENT");
-#ifdef CONFIG_ROLLBACK
- if (flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT)
- ccputs(" rollback_at_boot");
- if (flags & EC_FLASH_PROTECT_ROLLBACK_NOW)
- ccputs(" rollback_now");
-#endif
- ccputs("\n");
-
- ccputs("Protected now:");
- for (i = 0; i < PHYSICAL_BANKS; i++) {
- if (!(i & 31))
- ccputs("\n ");
- else if (!(i & 7))
- ccputs(" ");
- ccputs(crec_flash_physical_get_protect(i) ? "Y" : ".");
- }
- ccputs("\n");
- return EC_SUCCESS;
-}
-DECLARE_SAFE_CONSOLE_COMMAND(flashinfo, command_flash_info,
- NULL,
- "Print flash info");
-#endif /* CONFIG_CMD_FLASHINFO */
-
-#ifdef CONFIG_CMD_FLASH
-static int command_flash_erase(int argc, char **argv)
-{
- int offset = -1;
- int size = -1;
- int rv;
-
- if (crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW)
- return EC_ERROR_ACCESS_DENIED;
-
- rv = parse_offset_size(argc, argv, 1, &offset, &size);
- if (rv)
- return rv;
-
- ccprintf("Erasing %d bytes at 0x%x...\n", size, offset);
- return crec_flash_erase(offset, size);
-}
-DECLARE_CONSOLE_COMMAND(flasherase, command_flash_erase,
- "offset size",
- "Erase flash");
-
-static int command_flash_write(int argc, char **argv)
-{
- int offset = -1;
- int size = -1;
- int rv;
- char *data;
- int i;
-
- if (crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW)
- return EC_ERROR_ACCESS_DENIED;
-
- rv = parse_offset_size(argc, argv, 1, &offset, &size);
- if (rv)
- return rv;
-
- if (size > shared_mem_size())
- size = shared_mem_size();
-
- /* Acquire the shared memory buffer */
- rv = shared_mem_acquire(size, &data);
- if (rv) {
- ccputs("Can't get shared mem\n");
- return rv;
- }
-
- /* Fill the data buffer with a pattern */
- for (i = 0; i < size; i++)
- data[i] = i;
-
- ccprintf("Writing %d bytes to 0x%x...\n", size, offset);
- rv = crec_flash_write(offset, size, data);
-
- /* Free the buffer */
- shared_mem_release(data);
-
- return rv;
-}
-DECLARE_CONSOLE_COMMAND(flashwrite, command_flash_write,
- "offset size",
- "Write pattern to flash");
-
-static int command_flash_read(int argc, char **argv)
-{
- int offset = -1;
- int size = 256;
- int rv;
- char *data;
- int i;
-
- rv = parse_offset_size(argc, argv, 1, &offset, &size);
- if (rv)
- return rv;
-
- if (size > shared_mem_size())
- size = shared_mem_size();
-
- /* Acquire the shared memory buffer */
- rv = shared_mem_acquire(size, &data);
- if (rv) {
- ccputs("Can't get shared mem\n");
- return rv;
- }
-
- /* Read the data */
- if (crec_flash_read(offset, size, data)) {
- shared_mem_release(data);
- return EC_ERROR_INVAL;
- }
-
- /* Dump it */
- for (i = 0; i < size; i++) {
- if ((offset + i) % 16) {
- ccprintf(" %02x", data[i]);
- } else {
- ccprintf("\n%08x: %02x", offset + i, data[i]);
- cflush();
- }
- }
- ccprintf("\n");
-
- /* Free the buffer */
- shared_mem_release(data);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(flashread, command_flash_read,
- "offset [size]",
- "Read flash");
-#endif
-
-#ifdef CONFIG_CMD_FLASH_WP
-static int command_flash_wp(int argc, char **argv)
-{
- int val;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- if (!strcasecmp(argv[1], "now"))
- return crec_flash_set_protect(EC_FLASH_PROTECT_ALL_NOW, -1);
-
- if (!strcasecmp(argv[1], "all"))
- return crec_flash_set_protect(EC_FLASH_PROTECT_ALL_AT_BOOT, -1);
-
- if (!strcasecmp(argv[1], "noall"))
- return crec_flash_set_protect(EC_FLASH_PROTECT_ALL_AT_BOOT, 0);
-
-#ifdef CONFIG_FLASH_PROTECT_RW
- if (!strcasecmp(argv[1], "rw"))
- return crec_flash_set_protect(EC_FLASH_PROTECT_RW_AT_BOOT, -1);
-
- if (!strcasecmp(argv[1], "norw"))
- return crec_flash_set_protect(EC_FLASH_PROTECT_RW_AT_BOOT, 0);
-#endif
-
-#ifdef CONFIG_ROLLBACK
- if (!strcasecmp(argv[1], "rb"))
- return crec_flash_set_protect(EC_FLASH_PROTECT_ROLLBACK_AT_BOOT,
- -1);
-
- if (!strcasecmp(argv[1], "norb"))
- return crec_flash_set_protect(EC_FLASH_PROTECT_ROLLBACK_AT_BOOT,
- 0);
-#endif
-
- /* Do this last, since anything starting with 'n' means "no" */
- if (parse_bool(argv[1], &val))
- return crec_flash_set_protect(EC_FLASH_PROTECT_RO_AT_BOOT,
- val ? -1 : 0);
-
- return EC_ERROR_PARAM1;
-}
-DECLARE_CONSOLE_COMMAND(flashwp, command_flash_wp,
- "<BOOLEAN> | now | all | noall"
-#ifdef CONFIG_FLASH_PROTECT_RW
- " | rw | norw"
-#endif
-#ifdef CONFIG_ROLLBACK
- " | rb | norb"
-#endif
- , "Modify flash write protect");
-#endif /* CONFIG_CMD_FLASH_WP */
-
-/*****************************************************************************/
-/* Host commands */
-
-/*
- * All internal EC code assumes that offsets are provided relative to
- * physical address zero of storage. In some cases, the region of storage
- * belonging to the EC is not physical address zero - a non-zero fmap_base
- * indicates so. Since fmap_base is not yet handled correctly by external
- * code, we must perform the adjustment in our host command handlers -
- * adjust all offsets so they are relative to the beginning of the storage
- * region belonging to the EC. TODO(crbug.com/529365): Handle fmap_base
- * correctly in flashrom, dump_fmap, etc. and remove EC_FLASH_REGION_START.
- */
-#define EC_FLASH_REGION_START MIN(CONFIG_EC_PROTECTED_STORAGE_OFF, \
- CONFIG_EC_WRITABLE_STORAGE_OFF)
-
-static enum ec_status flash_command_get_info(struct host_cmd_handler_args *args)
-{
- const struct ec_params_flash_info_2 *p_2 = args->params;
- struct ec_response_flash_info_2 *r_2 = args->response;
-#ifdef CONFIG_FLASH_MULTIPLE_REGION
- int banks_size = ARRAY_SIZE(flash_bank_array);
- const struct ec_flash_bank *banks = flash_bank_array;
-#else
- struct ec_response_flash_info_1 *r_1 = args->response;
-#if CONFIG_FLASH_BANK_SIZE < CONFIG_FLASH_ERASE_SIZE
-#error "Flash: Bank size expected bigger or equal to erase size."
-#endif
- struct ec_flash_bank single_bank = {
- .count = CONFIG_FLASH_SIZE_BYTES / CONFIG_FLASH_BANK_SIZE,
- .size_exp = __fls(CONFIG_FLASH_BANK_SIZE),
- .write_size_exp = __fls(CONFIG_FLASH_WRITE_SIZE),
- .erase_size_exp = __fls(CONFIG_FLASH_ERASE_SIZE),
- .protect_size_exp = __fls(CONFIG_FLASH_BANK_SIZE),
- };
- int banks_size = 1;
- const struct ec_flash_bank *banks = &single_bank;
-#endif
- int banks_len;
- int ideal_size;
-
- /*
- * Compute the ideal amount of data for the host to send us,
- * based on the maximum response size and the ideal write size.
- */
- ideal_size = (args->response_max -
- sizeof(struct ec_params_flash_write)) &
- ~(CONFIG_FLASH_WRITE_IDEAL_SIZE - 1);
- /*
- * If we can't get at least one ideal block, then just want
- * as high a multiple of the minimum write size as possible.
- */
- if (!ideal_size)
- ideal_size = (args->response_max -
- sizeof(struct ec_params_flash_write)) &
- ~(CONFIG_FLASH_WRITE_SIZE - 1);
-
-
- if (args->version >= 2) {
- args->response_size = sizeof(struct ec_response_flash_info_2);
- r_2->flash_size =
- CONFIG_FLASH_SIZE_BYTES - EC_FLASH_REGION_START;
-#if (CONFIG_FLASH_ERASED_VALUE32 == 0)
- r_2->flags = EC_FLASH_INFO_ERASE_TO_0;
-#else
- r_2->flags = 0;
-#endif
-#ifdef CONFIG_FLASH_SELECT_REQUIRED
- r_2->flags |= EC_FLASH_INFO_SELECT_REQUIRED;
-#endif
- r_2->write_ideal_size = ideal_size;
- r_2->num_banks_total = banks_size;
- r_2->num_banks_desc = MIN(banks_size, p_2->num_banks_desc);
- banks_len = r_2->num_banks_desc * sizeof(struct ec_flash_bank);
- memcpy(r_2->banks, banks, banks_len);
- args->response_size += banks_len;
- return EC_RES_SUCCESS;
- }
-#ifdef CONFIG_FLASH_MULTIPLE_REGION
- return EC_RES_INVALID_PARAM;
-#else
- r_1->flash_size = CONFIG_FLASH_SIZE_BYTES - EC_FLASH_REGION_START;
- r_1->flags = 0;
- r_1->write_block_size = CONFIG_FLASH_WRITE_SIZE;
- r_1->erase_block_size = CONFIG_FLASH_ERASE_SIZE;
- r_1->protect_block_size = CONFIG_FLASH_BANK_SIZE;
- if (args->version == 0) {
- /* Only version 0 fields returned */
- args->response_size = sizeof(struct ec_response_flash_info);
- } else {
- args->response_size = sizeof(struct ec_response_flash_info_1);
- /* Fill in full version 1 struct */
- r_1->write_ideal_size = ideal_size;
-#if (CONFIG_FLASH_ERASED_VALUE32 == 0)
- r_1->flags |= EC_FLASH_INFO_ERASE_TO_0;
-#endif
-#ifdef CONFIG_FLASH_SELECT_REQUIRED
- r_1->flags |= EC_FLASH_INFO_SELECT_REQUIRED;
-#endif
- }
- return EC_RES_SUCCESS;
-#endif /* CONFIG_FLASH_MULTIPLE_REGION */
-}
-#ifdef CONFIG_FLASH_MULTIPLE_REGION
-#define FLASH_INFO_VER EC_VER_MASK(2)
-#else
-#define FLASH_INFO_VER (EC_VER_MASK(0) | EC_VER_MASK(1) | EC_VER_MASK(2))
-#endif
-DECLARE_HOST_COMMAND(EC_CMD_FLASH_INFO,
- flash_command_get_info, FLASH_INFO_VER);
-
-
-static enum ec_status flash_command_read(struct host_cmd_handler_args *args)
-{
- const struct ec_params_flash_read *p = args->params;
- uint32_t offset = p->offset + EC_FLASH_REGION_START;
-
- if (p->size > args->response_max)
- return EC_RES_OVERFLOW;
-
- if (crec_flash_read(offset, p->size, args->response))
- return EC_RES_ERROR;
-
- args->response_size = p->size;
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_FLASH_READ,
- flash_command_read,
- EC_VER_MASK(0));
-
-/**
- * Flash write command
- *
- * Version 0 and 1 are equivalent from the EC-side; the only difference is
- * that the host can only send 64 bytes of data at a time in version 0.
- */
-static enum ec_status flash_command_write(struct host_cmd_handler_args *args)
-{
- const struct ec_params_flash_write *p = args->params;
- uint32_t offset = p->offset + EC_FLASH_REGION_START;
-
- if (crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW)
- return EC_RES_ACCESS_DENIED;
-
- if (p->size + sizeof(*p) > args->params_size)
- return EC_RES_INVALID_PARAM;
-
-#ifdef CONFIG_INTERNAL_STORAGE
- if (system_unsafe_to_overwrite(offset, p->size))
- return EC_RES_ACCESS_DENIED;
-#endif
-
- if (crec_flash_write(offset, p->size, (const uint8_t *)(p + 1)))
- return EC_RES_ERROR;
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_FLASH_WRITE,
- flash_command_write,
- EC_VER_MASK(0) | EC_VER_MASK(EC_VER_FLASH_WRITE));
-
-#ifndef CONFIG_FLASH_MULTIPLE_REGION
-/*
- * Make sure our image sizes are a multiple of flash block erase size so that
- * the host can erase the entire image.
- * Note that host (flashrom/depthcharge) does not erase/program the
- * EC_FLASH_REGION_RO region, it only queries this region.
- */
-BUILD_ASSERT(CONFIG_WP_STORAGE_SIZE % CONFIG_FLASH_ERASE_SIZE == 0);
-BUILD_ASSERT(CONFIG_EC_WRITABLE_STORAGE_SIZE % CONFIG_FLASH_ERASE_SIZE == 0);
-
-#endif
-
-static enum ec_status flash_command_erase(struct host_cmd_handler_args *args)
-{
- const struct ec_params_flash_erase *p = args->params;
- int rc = EC_RES_SUCCESS, cmd = FLASH_ERASE_SECTOR;
- uint32_t offset;
-#ifdef CONFIG_FLASH_DEFERRED_ERASE
- const struct ec_params_flash_erase_v1 *p_1 = args->params;
-
- if (args->version > 0) {
- cmd = p_1->cmd;
- p = &p_1->params;
- }
-#endif
- offset = p->offset + EC_FLASH_REGION_START;
-
- if (crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW)
- return EC_RES_ACCESS_DENIED;
-
-#ifdef CONFIG_INTERNAL_STORAGE
- if (system_unsafe_to_overwrite(offset, p->size))
- return EC_RES_ACCESS_DENIED;
-#endif
-
- switch (cmd) {
- case FLASH_ERASE_SECTOR:
-#if defined(HAS_TASK_HOSTCMD) && defined(CONFIG_HOST_COMMAND_STATUS)
- args->result = EC_RES_IN_PROGRESS;
- host_send_response(args);
-#endif
- if (crec_flash_erase(offset, p->size))
- return EC_RES_ERROR;
-
- break;
-#ifdef CONFIG_FLASH_DEFERRED_ERASE
- case FLASH_ERASE_SECTOR_ASYNC:
- rc = erase_rc;
- if (rc == EC_RES_SUCCESS) {
- memcpy(&erase_info, p_1, sizeof(*p_1));
- hook_call_deferred(&flash_erase_deferred_data,
- 100 * MSEC);
- } else {
- /*
- * Not our job to return the result of
- * the previous command.
- */
- rc = EC_RES_BUSY;
- }
- break;
- case FLASH_ERASE_GET_RESULT:
- rc = erase_rc;
- if (rc != EC_RES_BUSY)
- /* Ready for another command */
- erase_rc = EC_RES_SUCCESS;
- break;
-#endif
- default:
- rc = EC_RES_INVALID_PARAM;
- }
- return rc;
-}
-
-
-DECLARE_HOST_COMMAND(EC_CMD_FLASH_ERASE, flash_command_erase,
- EC_VER_MASK(0)
-#ifdef CONFIG_FLASH_DEFERRED_ERASE
- | EC_VER_MASK(1)
-#endif
- );
-
-static enum ec_status flash_command_protect(struct host_cmd_handler_args *args)
-{
- const struct ec_params_flash_protect *p = args->params;
- struct ec_response_flash_protect *r = args->response;
-
- /*
- * Handle requesting new flags. Note that we ignore the return code
- * from flash_set_protect(), since errors will be visible to the caller
- * via the flags in the response. (If we returned error, the caller
- * wouldn't get the response.)
- */
- if (p->mask)
- crec_flash_set_protect(p->mask, p->flags);
-
- /*
- * Retrieve the current flags. The caller can use this to determine
- * which of the requested flags could be set. This is cleaner than
- * simply returning error, because it provides information to the
- * caller about the actual result.
- */
- r->flags = crec_flash_get_protect();
-
- /* Indicate which flags are valid on this platform */
- r->valid_flags =
- EC_FLASH_PROTECT_GPIO_ASSERTED |
- EC_FLASH_PROTECT_ERROR_STUCK |
- EC_FLASH_PROTECT_ERROR_INCONSISTENT |
- crec_flash_physical_get_valid_flags();
- r->writable_flags = crec_flash_physical_get_writable_flags(r->flags);
-
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-
-/*
- * TODO(crbug.com/239197) : Adding both versions to the version mask is a
- * temporary workaround for a problem in the cros_ec driver. Drop
- * EC_VER_MASK(0) once cros_ec driver can send the correct version.
- */
-DECLARE_HOST_COMMAND(EC_CMD_FLASH_PROTECT,
- flash_command_protect,
- EC_VER_MASK(0) | EC_VER_MASK(1));
-
-static enum ec_status
-flash_command_region_info(struct host_cmd_handler_args *args)
-{
- const struct ec_params_flash_region_info *p = args->params;
- struct ec_response_flash_region_info *r = args->response;
-
- switch (p->region) {
- case EC_FLASH_REGION_RO:
- r->offset = CONFIG_EC_PROTECTED_STORAGE_OFF +
- CONFIG_RO_STORAGE_OFF -
- EC_FLASH_REGION_START;
- r->size = EC_FLASH_REGION_RO_SIZE;
- break;
- case EC_FLASH_REGION_ACTIVE:
- r->offset = flash_get_rw_offset(system_get_active_copy()) -
- EC_FLASH_REGION_START;
- r->size = CONFIG_EC_WRITABLE_STORAGE_SIZE;
- break;
- case EC_FLASH_REGION_WP_RO:
- r->offset = CONFIG_WP_STORAGE_OFF -
- EC_FLASH_REGION_START;
- r->size = CONFIG_WP_STORAGE_SIZE;
- break;
- case EC_FLASH_REGION_UPDATE:
- r->offset = flash_get_rw_offset(system_get_update_copy()) -
- EC_FLASH_REGION_START;
- r->size = CONFIG_EC_WRITABLE_STORAGE_SIZE;
- break;
- default:
- return EC_RES_INVALID_PARAM;
- }
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_FLASH_REGION_INFO,
- flash_command_region_info,
- EC_VER_MASK(EC_VER_FLASH_REGION_INFO));
-
-
-#ifdef CONFIG_FLASH_SELECT_REQUIRED
-
-static enum ec_status flash_command_select(struct host_cmd_handler_args *args)
-{
- const struct ec_params_flash_select *p = args->params;
-
- return crec_board_flash_select(p->select);
-}
-DECLARE_HOST_COMMAND(EC_CMD_FLASH_SELECT,
- flash_command_select,
- EC_VER_MASK(0));
-
-#endif /* CONFIG_FLASH_SELECT_REQUIRED */
diff --git a/common/fmap.c b/common/fmap.c
deleted file mode 100644
index 47fa75f0e9..0000000000
--- a/common/fmap.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Copyright 2012 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.
- */
-
-#include <stddef.h>
-
-#include "common.h"
-#include "cros_version.h"
-#include "rwsig.h"
-#include "util.h"
-
-/*
- * FMAP structs.
- * See https://chromium.googlesource.com/chromiumos/third_party/flashmap/+/master/lib/fmap.h
- */
-#define FMAP_NAMELEN 32
-#define FMAP_SIGNATURE "__FMAP__"
-#define FMAP_SIGNATURE_SIZE 8
-#define FMAP_VER_MAJOR 1
-#define FMAP_VER_MINOR 0
-
-/*
- * For address containing CONFIG_PROGRAM_MEMORY_BASE (symbols in *.RO.lds.S and
- * variable), this computes the offset to the start of the image on flash.
- */
-#define RELATIVE_RO(addr) ((addr) - CONFIG_PROGRAM_MEMORY_BASE - \
- CONFIG_RO_MEM_OFF)
-
-/*
- * All internal EC code assumes that offsets are provided relative to
- * physical address zero of storage. In some cases, the region of storage
- * belonging to the EC is not physical address zero - a non-zero fmap_base
- * indicates so. Since fmap_base is not yet handled correctly by external
- * code, we must perform the adjustment in our host command handlers -
- * adjust all offsets so they are relative to the beginning of the storage
- * region belonging to the EC. TODO(crbug.com/529365): Handle fmap_base
- * correctly in flashrom, dump_fmap, etc. and remove EC_FLASH_REGION_START.
- */
-#if CONFIG_EC_WRITABLE_STORAGE_OFF < CONFIG_EC_PROTECTED_STORAGE_OFF
-#define FMAP_REGION_START CONFIG_EC_WRITABLE_STORAGE_OFF
-#else
-#define FMAP_REGION_START CONFIG_EC_PROTECTED_STORAGE_OFF
-#endif
-
-struct fmap_header {
- char fmap_signature[FMAP_SIGNATURE_SIZE];
- uint8_t fmap_ver_major;
- uint8_t fmap_ver_minor;
- uint64_t fmap_base;
- uint32_t fmap_size;
- char fmap_name[FMAP_NAMELEN];
- uint16_t fmap_nareas;
-} __packed;
-
-#define FMAP_AREA_STATIC BIT(0) /* can be checksummed */
-#define FMAP_AREA_COMPRESSED BIT(1) /* may be compressed */
-#define FMAP_AREA_RO BIT(2) /* writes may fail */
-
-struct fmap_area_header {
- uint32_t area_offset;
- uint32_t area_size;
- char area_name[FMAP_NAMELEN];
- uint16_t area_flags;
-} __packed;
-
-#ifdef CONFIG_RWSIG_TYPE_RWSIG
-#define NUM_EC_FMAP_AREAS_RWSIG 2
-#else
-#define NUM_EC_FMAP_AREAS_RWSIG 0
-#endif
-
-#ifdef CONFIG_ROLLBACK
-#define NUM_EC_FMAP_AREAS_ROLLBACK 1
-#else
-#define NUM_EC_FMAP_AREAS_ROLLBACK 0
-#endif
-#ifdef CONFIG_RW_B
-# ifdef CONFIG_RWSIG_TYPE_RWSIG
-# define NUM_EC_FMAP_AREAS_RW_B 2
-# else
-# define NUM_EC_FMAP_AREAS_RW_B 1
-# endif
-#else
-#define NUM_EC_FMAP_AREAS_RW_B 0
-#endif
-
-#define NUM_EC_FMAP_AREAS (7 + \
- NUM_EC_FMAP_AREAS_RWSIG + \
- NUM_EC_FMAP_AREAS_ROLLBACK + \
- NUM_EC_FMAP_AREAS_RW_B)
-
-const struct _ec_fmap {
- struct fmap_header header;
- struct fmap_area_header area[NUM_EC_FMAP_AREAS];
-} ec_fmap __keep __attribute__((section(".google"))) = {
- /* Header */
- {
- .fmap_signature = {'_', '_', 'F', 'M', 'A', 'P', '_', '_'},
- .fmap_ver_major = FMAP_VER_MAJOR,
- .fmap_ver_minor = FMAP_VER_MINOR,
- .fmap_base = CONFIG_PROGRAM_MEMORY_BASE,
- .fmap_size = CONFIG_FLASH_SIZE_BYTES,
- /* Used to distinguish the EC FMAP from other FMAPs */
- .fmap_name = "EC_FMAP",
- .fmap_nareas = NUM_EC_FMAP_AREAS,
- },
-
- {
- /* RO Firmware */
- {
- /*
- * Range of RO firmware to be updated. EC_RO
- * section includes the bootloader section
- * because it may need to be updated/paired
- * with a different RO. Verified in factory
- * finalization by hash. Should not have
- * volatile data (ex, calibration results).
- */
- .area_name = "EC_RO",
- .area_offset = CONFIG_EC_PROTECTED_STORAGE_OFF -
- FMAP_REGION_START,
- .area_size = CONFIG_RO_SIZE + CONFIG_RO_STORAGE_OFF,
- .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO,
- },
- {
- /* (Optional) RO firmware code. */
- .area_name = "FR_MAIN",
- .area_offset = CONFIG_EC_PROTECTED_STORAGE_OFF -
- FMAP_REGION_START + CONFIG_RO_STORAGE_OFF,
- .area_size = CONFIG_RO_SIZE,
- .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO,
- },
- {
- /*
- * RO firmware version ID. Must be NULL terminated
- * ASCII, and padded with \0.
- */
- .area_name = "RO_FRID",
- .area_offset = CONFIG_EC_PROTECTED_STORAGE_OFF -
- FMAP_REGION_START + CONFIG_RO_STORAGE_OFF +
- RELATIVE_RO((uint32_t)__image_data_offset) +
- offsetof(struct image_data, version),
- .area_size = sizeof(current_image_data.version),
- .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO,
- },
-
- /* Other RO stuff: FMAP, WP, KEYS, etc. */
- {
- .area_name = "FMAP",
- .area_offset = CONFIG_EC_PROTECTED_STORAGE_OFF -
- FMAP_REGION_START + CONFIG_RO_STORAGE_OFF +
- RELATIVE_RO((uint32_t)&ec_fmap),
- .area_size = sizeof(ec_fmap),
- .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO,
- },
- {
- /*
- * The range for write protection, for factory
- * finalization. Should include (may be identical to)
- * EC_RO and aligned to hardware specification.
- */
- .area_name = "WP_RO",
- .area_offset = CONFIG_WP_STORAGE_OFF -
- FMAP_REGION_START,
- .area_size = CONFIG_WP_STORAGE_SIZE,
- .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO,
- },
-#ifdef CONFIG_RWSIG_TYPE_RWSIG
- {
- /* RO public key address, for RW verification */
- .area_name = "KEY_RO",
- .area_offset = CONFIG_EC_PROTECTED_STORAGE_OFF -
- FMAP_REGION_START + CONFIG_RO_PUBKEY_ADDR -
- CONFIG_PROGRAM_MEMORY_BASE,
- .area_size = CONFIG_RO_PUBKEY_SIZE,
- .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO,
- },
-#endif
-
- /* RW Firmware */
- {
- /* The range of RW firmware to be auto-updated. */
- .area_name = "EC_RW",
- .area_offset = CONFIG_EC_WRITABLE_STORAGE_OFF -
- FMAP_REGION_START + CONFIG_RW_STORAGE_OFF,
- .area_size = CONFIG_RW_SIZE,
- .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO,
- },
- {
- /*
- * RW firmware version ID. Must be NULL terminated
- * ASCII, and padded with \0.
- * TODO: Get the relative offset of
- * __image_data_offset within our RW image to
- * accommodate image asymmetry.
- */
- .area_name = "RW_FWID",
- .area_offset = CONFIG_EC_WRITABLE_STORAGE_OFF -
- FMAP_REGION_START + CONFIG_RW_STORAGE_OFF +
- RELATIVE_RO((uint32_t)__image_data_offset) +
- offsetof(struct image_data, version),
- .area_size = sizeof(current_image_data.version),
- .area_flags = FMAP_AREA_STATIC,
- },
-#ifdef CONFIG_ROLLBACK
- {
- /*
- * RW rollback version, 32-bit unsigned integer.
- * TODO: Get the relative offset of
- * __image_data_offset within our RW image to
- * accommodate image asymmetry.
- */
- .area_name = "RW_RBVER",
- .area_offset = CONFIG_EC_WRITABLE_STORAGE_OFF -
- FMAP_REGION_START + CONFIG_RW_STORAGE_OFF +
- RELATIVE_RO((uint32_t)__image_data_offset) +
- offsetof(struct image_data, rollback_version),
- .area_size = sizeof(
- current_image_data.rollback_version),
- .area_flags = FMAP_AREA_STATIC,
- },
-#endif
-#ifdef CONFIG_RWSIG_TYPE_RWSIG
- {
- /* RW image signature */
- .area_name = "SIG_RW",
- .area_offset = CONFIG_EC_PROTECTED_STORAGE_OFF -
- FMAP_REGION_START + CONFIG_RW_SIG_ADDR -
- CONFIG_PROGRAM_MEMORY_BASE,
- .area_size = CONFIG_RW_SIG_SIZE,
- .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO,
- },
-#endif
-#ifdef CONFIG_RW_B
- /* RW Firmware */
- {
- /* The range of RW firmware to be auto-updated. */
- .area_name = "EC_RW_B",
- .area_offset = CONFIG_EC_WRITABLE_STORAGE_OFF -
- FMAP_REGION_START + CONFIG_RW_STORAGE_OFF +
- CONFIG_RW_SIZE,
- .area_size = CONFIG_RW_SIZE,
- .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO,
- },
-#ifdef CONFIG_RWSIG_TYPE_RWSIG
- {
- /* RW_B image signature */
- .area_name = "SIG_RW_B",
- .area_offset = CONFIG_EC_PROTECTED_STORAGE_OFF -
- FMAP_REGION_START + CONFIG_RW_B_SIG_ADDR -
- CONFIG_PROGRAM_MEMORY_BASE,
- .area_size = CONFIG_RW_SIG_SIZE,
- .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO,
- },
-#endif
-#endif
- }
-};
diff --git a/common/fpsensor/OWNERS b/common/fpsensor/OWNERS
deleted file mode 100644
index 395f722670..0000000000
--- a/common/fpsensor/OWNERS
+++ /dev/null
@@ -1,10 +0,0 @@
-# Fingerprint Sensor
-
-# Don't inherit owners from elsewhere in the manifest
-set noparent
-
-hesling@chromium.org
-jora@google.com
-josienordrum@google.com
-tomhughes@chromium.org
-yichengli@chromium.org
diff --git a/common/fpsensor/fpsensor.c b/common/fpsensor/fpsensor.c
deleted file mode 100644
index 25010c7db8..0000000000
--- a/common/fpsensor/fpsensor.c
+++ /dev/null
@@ -1,887 +0,0 @@
-/* Copyright 2017 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.
- */
-
-#include "atomic.h"
-#include "clock.h"
-#include "common.h"
-#include "console.h"
-#include "cryptoc/util.h"
-#include "ec_commands.h"
-#include "fpsensor.h"
-#include "fpsensor_crypto.h"
-#include "fpsensor_detect.h"
-#include "fpsensor_private.h"
-#include "fpsensor_state.h"
-#include "gpio.h"
-#include "host_command.h"
-#include "link_defs.h"
-#include "mkbp_event.h"
-#include "overflow.h"
-#include "spi.h"
-#include "system.h"
-#include "task.h"
-#include "trng.h"
-#include "util.h"
-#include "watchdog.h"
-
-#if !defined(CONFIG_RNG)
-#error "fpsensor requires RNG"
-#endif
-
-#if defined(SECTION_IS_RO)
-#error "fpsensor code should not be in RO image."
-#endif
-
-/* Ready to encrypt a template. */
-static timestamp_t encryption_deadline;
-
-/* raw image offset inside the acquired frame */
-#ifndef FP_SENSOR_IMAGE_OFFSET
-#define FP_SENSOR_IMAGE_OFFSET 0
-#endif
-
-#define FP_MODE_ANY_CAPTURE (FP_MODE_CAPTURE | FP_MODE_ENROLL_IMAGE | \
- FP_MODE_MATCH)
-#define FP_MODE_ANY_DETECT_FINGER (FP_MODE_FINGER_DOWN | FP_MODE_FINGER_UP | \
- FP_MODE_ANY_CAPTURE)
-#define FP_MODE_ANY_WAIT_IRQ (FP_MODE_FINGER_DOWN | FP_MODE_ANY_CAPTURE)
-
-/* Delay between 2 s of the sensor to detect finger removal */
-#define FINGER_POLLING_DELAY (100*MSEC)
-
-/* Timing statistics. */
-static uint32_t capture_time_us;
-static uint32_t matching_time_us;
-static uint32_t overall_time_us;
-static timestamp_t overall_t0;
-static uint8_t timestamps_invalid;
-
-BUILD_ASSERT(sizeof(struct ec_fp_template_encryption_metadata) % 4 == 0);
-
-/* Interrupt line from the fingerprint sensor */
-void fps_event(enum gpio_signal signal)
-{
- task_set_event(TASK_ID_FPSENSOR, TASK_EVENT_SENSOR_IRQ);
-}
-
-static void send_mkbp_event(uint32_t event)
-{
- atomic_or(&fp_events, event);
- mkbp_send_event(EC_MKBP_EVENT_FINGERPRINT);
-}
-
-static inline int is_raw_capture(uint32_t mode)
-{
- int capture_type = FP_CAPTURE_TYPE(mode);
-
- return (capture_type == FP_CAPTURE_VENDOR_FORMAT
- || capture_type == FP_CAPTURE_QUALITY_TEST);
-}
-
-#ifdef HAVE_FP_PRIVATE_DRIVER
-static inline int is_test_capture(uint32_t mode)
-{
- int capture_type = FP_CAPTURE_TYPE(mode);
-
- return (mode & FP_MODE_CAPTURE)
- && (capture_type == FP_CAPTURE_PATTERN0
- || capture_type == FP_CAPTURE_PATTERN1
- || capture_type == FP_CAPTURE_RESET_TEST);
-}
-
-/*
- * contains the bit FP_MODE_ENROLL_SESSION if a finger enrollment is on-going.
- * It is used to detect the ENROLL_SESSION transition when sensor_mode is
- * updated by the host.
- */
-static uint32_t enroll_session;
-
-static uint32_t fp_process_enroll(void)
-{
- int percent = 0;
- int res;
-
- if (template_newly_enrolled != FP_NO_SUCH_TEMPLATE)
- CPRINTS("Warning: previously enrolled template has not been "
- "read yet.");
-
- /* begin/continue enrollment */
- CPRINTS("[%d]Enrolling ...", templ_valid);
- res = fp_finger_enroll(fp_buffer, &percent);
- CPRINTS("[%d]Enroll =>%d (%d%%)", templ_valid, res, percent);
- if (res < 0)
- return EC_MKBP_FP_ENROLL
- | EC_MKBP_FP_ERRCODE(EC_MKBP_FP_ERR_ENROLL_INTERNAL);
- templ_dirty |= BIT(templ_valid);
- if (percent == 100) {
- res = fp_enrollment_finish(fp_template[templ_valid]);
- if (res) {
- res = EC_MKBP_FP_ERR_ENROLL_INTERNAL;
- } else {
- template_newly_enrolled = templ_valid;
- fp_enable_positive_match_secret(templ_valid,
- &positive_match_secret_state);
- templ_valid++;
- }
- sensor_mode &= ~FP_MODE_ENROLL_SESSION;
- enroll_session &= ~FP_MODE_ENROLL_SESSION;
- }
- return EC_MKBP_FP_ENROLL | EC_MKBP_FP_ERRCODE(res)
- | (percent << EC_MKBP_FP_ENROLL_PROGRESS_OFFSET);
-}
-
-static bool fp_match_success(int match_result)
-{
- if (match_result == EC_MKBP_FP_ERR_MATCH_YES ||
- match_result == EC_MKBP_FP_ERR_MATCH_YES_UPDATED ||
- match_result == EC_MKBP_FP_ERR_MATCH_YES_UPDATE_FAILED) {
- return true;
- }
-
- return false;
-}
-
-static uint32_t fp_process_match(void)
-{
- timestamp_t t0 = get_time();
- int res = -1;
- uint32_t updated = 0;
- int32_t fgr = FP_NO_SUCH_TEMPLATE;
-
- /* match finger against current templates */
- fp_disable_positive_match_secret(&positive_match_secret_state);
- CPRINTS("Matching/%d ...", templ_valid);
- if (templ_valid) {
- res = fp_finger_match(fp_template[0], templ_valid, fp_buffer,
- &fgr, &updated);
- CPRINTS("Match =>%d (finger %d)", res, fgr);
-
- if (fp_match_success(res)) {
- /*
- * Match succeded! Let's check if template number
- * is valid. If it is not valid, overwrite result
- * with EC_MKBP_FP_ERR_MATCH_NO_INTERNAL.
- */
- if (fgr >= 0 && fgr < FP_MAX_FINGER_COUNT) {
- fp_enable_positive_match_secret(fgr,
- &positive_match_secret_state);
- } else {
- res = EC_MKBP_FP_ERR_MATCH_NO_INTERNAL;
- }
- } else if (res < 0) {
- /*
- * Negative result means that there is a problem with
- * code responsible for matching. Overwrite it with
- * MATCH_NO_INTERNAL to let upper layers know what
- * happened.
- */
- res = EC_MKBP_FP_ERR_MATCH_NO_INTERNAL;
- }
-
- if (res == EC_MKBP_FP_ERR_MATCH_YES_UPDATED)
- templ_dirty |= updated;
- } else {
- CPRINTS("No enrolled templates");
- res = EC_MKBP_FP_ERR_MATCH_NO_TEMPLATES;
- }
-
- if (!fp_match_success(res))
- timestamps_invalid |= FPSTATS_MATCHING_INV;
-
- matching_time_us = time_since32(t0);
- return EC_MKBP_FP_MATCH | EC_MKBP_FP_ERRCODE(res)
- | ((fgr << EC_MKBP_FP_MATCH_IDX_OFFSET) & EC_MKBP_FP_MATCH_IDX_MASK);
-}
-
-static void fp_process_finger(void)
-{
- timestamp_t t0 = get_time();
- int res = fp_sensor_acquire_image_with_mode(fp_buffer,
- FP_CAPTURE_TYPE(sensor_mode));
- capture_time_us = time_since32(t0);
- if (!res) {
- uint32_t evt = EC_MKBP_FP_IMAGE_READY;
-
- /* Clean up SPI before clocking up to avoid hang on the dsb
- * in dma_go. Ignore the return value to let the WDT reboot
- * the MCU (and avoid getting trapped in the loop).
- * b/112781659 */
- res = spi_transaction_flush(&spi_devices[0]);
- if (res)
- CPRINTS("Failed to flush SPI: 0x%x", res);
- /* we need CPU power to do the computations */
- clock_enable_module(MODULE_FAST_CPU, 1);
-
- if (sensor_mode & FP_MODE_ENROLL_IMAGE)
- evt = fp_process_enroll();
- else if (sensor_mode & FP_MODE_MATCH)
- evt = fp_process_match();
-
- sensor_mode &= ~FP_MODE_ANY_CAPTURE;
- overall_time_us = time_since32(overall_t0);
- send_mkbp_event(evt);
-
- /* go back to lower power mode */
- clock_enable_module(MODULE_FAST_CPU, 0);
- } else {
- timestamps_invalid |= FPSTATS_CAPTURE_INV;
- }
-}
-#endif /* HAVE_FP_PRIVATE_DRIVER */
-
-void fp_task(void)
-{
- int timeout_us = -1;
-
- CPRINTS("FP_SENSOR_SEL: %s",
- fp_sensor_type_to_str(get_fp_sensor_type()));
-
-#ifdef HAVE_FP_PRIVATE_DRIVER
- /* Reset and initialize the sensor IC */
- fp_sensor_init();
-
- while (1) {
- uint32_t evt;
- enum finger_state st = FINGER_NONE;
-
- /* Wait for a sensor IRQ or a new mode configuration */
- evt = task_wait_event(timeout_us);
-
- if (evt & TASK_EVENT_UPDATE_CONFIG) {
- uint32_t mode = sensor_mode;
-
- gpio_disable_interrupt(GPIO_FPS_INT);
- if ((mode ^ enroll_session) & FP_MODE_ENROLL_SESSION) {
- if (mode & FP_MODE_ENROLL_SESSION) {
- if (fp_enrollment_begin())
- sensor_mode &=
- ~FP_MODE_ENROLL_SESSION;
- } else {
- fp_enrollment_finish(NULL);
- }
- enroll_session =
- sensor_mode & FP_MODE_ENROLL_SESSION;
- }
- if (is_test_capture(mode)) {
- fp_sensor_acquire_image_with_mode(fp_buffer,
- FP_CAPTURE_TYPE(mode));
- sensor_mode &= ~FP_MODE_CAPTURE;
- send_mkbp_event(EC_MKBP_FP_IMAGE_READY);
- continue;
- } else if (sensor_mode & FP_MODE_ANY_DETECT_FINGER) {
- /* wait for a finger on the sensor */
- fp_sensor_configure_detect();
- }
- if (sensor_mode & FP_MODE_DEEPSLEEP)
- /* Shutdown the sensor */
- fp_sensor_low_power();
- if (sensor_mode & FP_MODE_FINGER_UP)
- /* Poll the sensor to detect finger removal */
- timeout_us = FINGER_POLLING_DELAY;
- else
- timeout_us = -1;
- if (mode & FP_MODE_ANY_WAIT_IRQ) {
- gpio_enable_interrupt(GPIO_FPS_INT);
- } else if (mode & FP_MODE_RESET_SENSOR) {
- fp_reset_and_clear_context();
- sensor_mode &= ~FP_MODE_RESET_SENSOR;
- } else if (mode & FP_MODE_SENSOR_MAINTENANCE) {
- fp_maintenance();
- sensor_mode &= ~FP_MODE_SENSOR_MAINTENANCE;
- } else {
- fp_sensor_low_power();
- }
- } else if (evt & (TASK_EVENT_SENSOR_IRQ | TASK_EVENT_TIMER)) {
- overall_t0 = get_time();
- timestamps_invalid = 0;
- gpio_disable_interrupt(GPIO_FPS_INT);
- if (sensor_mode & FP_MODE_ANY_DETECT_FINGER) {
- st = fp_sensor_finger_status();
- if (st == FINGER_PRESENT &&
- sensor_mode & FP_MODE_FINGER_DOWN) {
- CPRINTS("Finger!");
- sensor_mode &= ~FP_MODE_FINGER_DOWN;
- send_mkbp_event(EC_MKBP_FP_FINGER_DOWN);
- }
- if (st == FINGER_NONE &&
- sensor_mode & FP_MODE_FINGER_UP) {
- sensor_mode &= ~FP_MODE_FINGER_UP;
- timeout_us = -1;
- send_mkbp_event(EC_MKBP_FP_FINGER_UP);
- }
- }
-
- if (st == FINGER_PRESENT &&
- sensor_mode & FP_MODE_ANY_CAPTURE)
- fp_process_finger();
-
- if (sensor_mode & FP_MODE_ANY_WAIT_IRQ) {
- fp_sensor_configure_detect();
- gpio_enable_interrupt(GPIO_FPS_INT);
- } else {
- fp_sensor_low_power();
- }
- }
- }
-#else /* !HAVE_FP_PRIVATE_DRIVER */
- while (1) {
- uint32_t evt = task_wait_event(timeout_us);
-
- send_mkbp_event(evt);
- }
-#endif /* !HAVE_FP_PRIVATE_DRIVER */
-}
-
-static enum ec_status fp_command_passthru(struct host_cmd_handler_args *args)
-{
- const struct ec_params_fp_passthru *params = args->params;
- void *out = args->response;
- int rc;
- int ret = EC_RES_SUCCESS;
-
- if (system_is_locked())
- return EC_RES_ACCESS_DENIED;
-
- if (params->len > args->params_size +
- offsetof(struct ec_params_fp_passthru, data) ||
- params->len > args->response_max)
- return EC_RES_INVALID_PARAM;
-
- rc = spi_transaction_async(&spi_devices[0], params->data,
- params->len, out, SPI_READBACK_ALL);
- if (params->flags & EC_FP_FLAG_NOT_COMPLETE)
- rc |= spi_transaction_wait(&spi_devices[0]);
- else
- rc |= spi_transaction_flush(&spi_devices[0]);
-
- if (rc == EC_ERROR_TIMEOUT)
- ret = EC_RES_TIMEOUT;
- else if (rc)
- ret = EC_RES_ERROR;
-
- args->response_size = params->len;
- return ret;
-}
-DECLARE_HOST_COMMAND(EC_CMD_FP_PASSTHRU, fp_command_passthru, EC_VER_MASK(0));
-
-static enum ec_status fp_command_info(struct host_cmd_handler_args *args)
-{
- struct ec_response_fp_info *r = args->response;
-
-#ifdef HAVE_FP_PRIVATE_DRIVER
- if (fp_sensor_get_info(r) < 0)
-#endif
- return EC_RES_UNAVAILABLE;
-
- r->template_size = FP_ALGORITHM_ENCRYPTED_TEMPLATE_SIZE;
- r->template_max = FP_MAX_FINGER_COUNT;
- r->template_valid = templ_valid;
- r->template_dirty = templ_dirty;
- r->template_version = FP_TEMPLATE_FORMAT_VERSION;
-
- /* V1 is identical to V0 with more information appended */
- args->response_size = args->version ? sizeof(*r) :
- sizeof(struct ec_response_fp_info_v0);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_FP_INFO, fp_command_info,
- EC_VER_MASK(0) | EC_VER_MASK(1));
-
-BUILD_ASSERT(FP_CONTEXT_NONCE_BYTES == 12);
-
-int validate_fp_buffer_offset(const uint32_t buffer_size, const uint32_t offset,
- const uint32_t size)
-{
- uint32_t bytes_requested;
-
- if (check_add_overflow(size, offset, &bytes_requested))
- return EC_ERROR_OVERFLOW;
-
- if (bytes_requested > buffer_size)
- return EC_ERROR_INVAL;
-
- return EC_SUCCESS;
-}
-
-static enum ec_status fp_command_frame(struct host_cmd_handler_args *args)
-{
- const struct ec_params_fp_frame *params = args->params;
- void *out = args->response;
- uint32_t idx = FP_FRAME_GET_BUFFER_INDEX(params->offset);
- uint32_t offset = params->offset & FP_FRAME_OFFSET_MASK;
- uint32_t size = params->size;
- uint32_t fgr;
- uint8_t key[SBP_ENC_KEY_LEN];
- struct ec_fp_template_encryption_metadata *enc_info;
- int ret;
-
- if (size > args->response_max)
- return EC_RES_INVALID_PARAM;
-
- if (idx == FP_FRAME_INDEX_RAW_IMAGE) {
- /* The host requested a frame. */
- if (system_is_locked())
- return EC_RES_ACCESS_DENIED;
- if (!is_raw_capture(sensor_mode))
- offset += FP_SENSOR_IMAGE_OFFSET;
-
- ret = validate_fp_buffer_offset(sizeof(fp_buffer), offset,
- size);
- if (ret != EC_SUCCESS)
- return EC_RES_INVALID_PARAM;
-
- memcpy(out, fp_buffer + offset, size);
- args->response_size = size;
- return EC_RES_SUCCESS;
- }
-
- /* The host requested a template. */
-
- /* Templates are numbered from 1 in this host request. */
- fgr = idx - FP_FRAME_INDEX_TEMPLATE;
-
- if (fgr >= FP_MAX_FINGER_COUNT)
- return EC_RES_INVALID_PARAM;
- if (fgr >= templ_valid)
- return EC_RES_UNAVAILABLE;
- ret = validate_fp_buffer_offset(sizeof(fp_enc_buffer), offset, size);
- if (ret != EC_SUCCESS)
- return EC_RES_INVALID_PARAM;
-
- if (!offset) {
- /* Host has requested the first chunk, do the encryption. */
- timestamp_t now = get_time();
- /* Encrypted template is after the metadata. */
- uint8_t *encrypted_template = fp_enc_buffer + sizeof(*enc_info);
- /* Positive match salt is after the template. */
- uint8_t *positive_match_salt =
- encrypted_template + sizeof(fp_template[0]);
- size_t encrypted_blob_size = sizeof(fp_template[0]) +
- sizeof(fp_positive_match_salt[0]);
-
- /* b/114160734: Not more than 1 encrypted message per second. */
- if (!timestamp_expired(encryption_deadline, &now))
- return EC_RES_BUSY;
- encryption_deadline.val = now.val + (1 * SECOND);
-
- memset(fp_enc_buffer, 0, sizeof(fp_enc_buffer));
- /*
- * The beginning of the buffer contains nonce, encryption_salt
- * and tag.
- */
- enc_info = (void *)fp_enc_buffer;
- enc_info->struct_version = FP_TEMPLATE_FORMAT_VERSION;
- init_trng();
- rand_bytes(enc_info->nonce, FP_CONTEXT_NONCE_BYTES);
- rand_bytes(enc_info->encryption_salt,
- FP_CONTEXT_ENCRYPTION_SALT_BYTES);
- exit_trng();
-
- if (fgr == template_newly_enrolled) {
- /*
- * Newly enrolled templates need new positive match
- * salt, new positive match secret and new validation
- * value.
- */
- template_newly_enrolled = FP_NO_SUCH_TEMPLATE;
- init_trng();
- rand_bytes(fp_positive_match_salt[fgr],
- FP_POSITIVE_MATCH_SALT_BYTES);
- exit_trng();
- }
-
- ret = derive_encryption_key(key, enc_info->encryption_salt);
- if (ret != EC_SUCCESS) {
- CPRINTS("fgr%d: Failed to derive key", fgr);
- return EC_RES_UNAVAILABLE;
- }
-
- /*
- * Copy the payload to |fp_enc_buffer| where it will be
- * encrypted in-place.
- */
- memcpy(encrypted_template, fp_template[fgr],
- sizeof(fp_template[0]));
- memcpy(positive_match_salt, fp_positive_match_salt[fgr],
- sizeof(fp_positive_match_salt[0]));
-
- /* Encrypt the secret blob in-place. */
- ret = aes_gcm_encrypt(key, SBP_ENC_KEY_LEN, encrypted_template,
- encrypted_template,
- encrypted_blob_size,
- enc_info->nonce, FP_CONTEXT_NONCE_BYTES,
- enc_info->tag, FP_CONTEXT_TAG_BYTES);
- always_memset(key, 0, sizeof(key));
- if (ret != EC_SUCCESS) {
- CPRINTS("fgr%d: Failed to encrypt template", fgr);
- return EC_RES_UNAVAILABLE;
- }
- templ_dirty &= ~BIT(fgr);
- }
- memcpy(out, fp_enc_buffer + offset, size);
- args->response_size = size;
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_FP_FRAME, fp_command_frame, EC_VER_MASK(0));
-
-static enum ec_status fp_command_stats(struct host_cmd_handler_args *args)
-{
- struct ec_response_fp_stats *r = args->response;
-
- r->capture_time_us = capture_time_us;
- r->matching_time_us = matching_time_us;
- r->overall_time_us = overall_time_us;
- r->overall_t0.lo = overall_t0.le.lo;
- r->overall_t0.hi = overall_t0.le.hi;
- r->timestamps_invalid = timestamps_invalid;
- /*
- * Note that this is set to FP_NO_SUCH_TEMPLATE when positive match
- * secret is read/disabled, and we are not using this field in biod.
- */
- r->template_matched = positive_match_secret_state.template_matched;
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_FP_STATS, fp_command_stats, EC_VER_MASK(0));
-
-static bool template_needs_validation_value(
- struct ec_fp_template_encryption_metadata *enc_info)
-{
- return enc_info->struct_version == 3
- && FP_TEMPLATE_FORMAT_VERSION == 4;
-}
-
-static int validate_template_format(
- struct ec_fp_template_encryption_metadata *enc_info)
-{
- if (template_needs_validation_value(enc_info))
- /* The host requested migration to v4. */
- return EC_RES_SUCCESS;
-
- if (enc_info->struct_version != FP_TEMPLATE_FORMAT_VERSION) {
- CPRINTS("Invalid template format %d", enc_info->struct_version);
- return EC_RES_INVALID_PARAM;
- }
- return EC_RES_SUCCESS;
-}
-
-static enum ec_status fp_command_template(struct host_cmd_handler_args *args)
-{
- const struct ec_params_fp_template *params = args->params;
- uint32_t size = params->size & ~FP_TEMPLATE_COMMIT;
- int xfer_complete = params->size & FP_TEMPLATE_COMMIT;
- uint32_t offset = params->offset;
- uint32_t idx = templ_valid;
- uint8_t key[SBP_ENC_KEY_LEN];
- struct ec_fp_template_encryption_metadata *enc_info;
- int ret;
-
- /* Can we store one more template ? */
- if (idx >= FP_MAX_FINGER_COUNT)
- return EC_RES_OVERFLOW;
-
- if (args->params_size !=
- size + offsetof(struct ec_params_fp_template, data))
- return EC_RES_INVALID_PARAM;
- ret = validate_fp_buffer_offset(sizeof(fp_enc_buffer), offset, size);
- if (ret != EC_SUCCESS)
- return EC_RES_INVALID_PARAM;
-
- memcpy(&fp_enc_buffer[offset], params->data, size);
-
- if (xfer_complete) {
- /* Encrypted template is after the metadata. */
- uint8_t *encrypted_template = fp_enc_buffer + sizeof(*enc_info);
- /* Positive match salt is after the template. */
- uint8_t *positive_match_salt =
- encrypted_template + sizeof(fp_template[0]);
- size_t encrypted_blob_size;
-
- /*
- * The complete encrypted template has been received, start
- * decryption.
- */
- fp_clear_finger_context(idx);
- /*
- * The beginning of the buffer contains nonce, encryption_salt
- * and tag.
- */
- enc_info = (void *)fp_enc_buffer;
- ret = validate_template_format(enc_info);
- if (ret != EC_RES_SUCCESS) {
- CPRINTS("fgr%d: Template format not supported", idx);
- return EC_RES_INVALID_PARAM;
- }
-
- if (enc_info->struct_version <= 3) {
- encrypted_blob_size = sizeof(fp_template[0]);
- } else {
- encrypted_blob_size =
- sizeof(fp_template[0]) +
- sizeof(fp_positive_match_salt[0]);
- }
-
- ret = derive_encryption_key(key, enc_info->encryption_salt);
- if (ret != EC_SUCCESS) {
- CPRINTS("fgr%d: Failed to derive key", idx);
- return EC_RES_UNAVAILABLE;
- }
-
- /* Decrypt the secret blob in-place. */
- ret = aes_gcm_decrypt(key, SBP_ENC_KEY_LEN, encrypted_template,
- encrypted_template,
- encrypted_blob_size,
- enc_info->nonce, FP_CONTEXT_NONCE_BYTES,
- enc_info->tag, FP_CONTEXT_TAG_BYTES);
- always_memset(key, 0, sizeof(key));
- if (ret != EC_SUCCESS) {
- CPRINTS("fgr%d: Failed to decipher template", idx);
- /* Don't leave bad data in the template buffer */
- fp_clear_finger_context(idx);
- return EC_RES_UNAVAILABLE;
- }
- memcpy(fp_template[idx], encrypted_template,
- sizeof(fp_template[0]));
- if (template_needs_validation_value(enc_info)) {
- CPRINTS("fgr%d: Generating positive match salt.", idx);
- init_trng();
- rand_bytes(positive_match_salt,
- FP_POSITIVE_MATCH_SALT_BYTES);
- exit_trng();
- }
- if (bytes_are_trivial(positive_match_salt,
- sizeof(fp_positive_match_salt[0]))) {
- CPRINTS("fgr%d: Trivial positive match salt.", idx);
- always_memset(fp_template[idx], 0,
- sizeof(fp_template[0]));
- return EC_RES_INVALID_PARAM;
- }
- memcpy(fp_positive_match_salt[idx], positive_match_salt,
- sizeof(fp_positive_match_salt[0]));
-
- templ_valid++;
- }
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_FP_TEMPLATE, fp_command_template, EC_VER_MASK(0));
-
-#ifdef CONFIG_CMD_FPSENSOR_DEBUG
-/* --- Debug console commands --- */
-
-/*
- * Send the current Fingerprint buffer to the host
- * it is formatted as an 8-bpp PGM ASCII file.
- *
- * In addition, it prepends a short Z-Modem download signature,
- * which triggers automatically your preferred viewer if you configure it
- * properly in "File transfer protocols" in the Minicom options menu.
- * (as triggered by Ctrl-A O)
- * +--------------------------------------------------------------------------+
- * | Name Program Name U/D FullScr IO-Red. Multi |
- * | A zmodem /usr/bin/sz -vv -b Y U N Y Y |
- * [...]
- * | L pgm /usr/bin/display_pgm N D N Y N |
- * | M Zmodem download string activates... L |
- *
- * My /usr/bin/display_pgm looks like this:
- * #!/bin/sh
- * TMPF=$(mktemp)
- * ascii-xfr -rdv ${TMPF}
- * display ${TMPF}
- *
- * Alternative (if you're using screen as your terminal):
- *
- * From *outside* the chroot:
- *
- * Install ascii-xfr: sudo apt-get install minicom
- * Install imagemagick: sudo apt-get install imagemagick
- *
- * Add the following to your ${HOME}/.screenrc:
- *
- * zmodem catch
- * zmodem recvcmd '!!! bash -c "ascii-xfr -rdv /tmp/finger.pgm && display /tmp/finger.pgm"'
- *
- * From *outside the chroot*, use screen to connect to UART console:
- *
- * sudo screen -c ${HOME}/.screenrc /dev/pts/NN 115200
- *
- */
-static void upload_pgm_image(uint8_t *frame)
-{
- int x, y;
- uint8_t *ptr = frame;
-
- /* fake Z-modem ZRQINIT signature */
- CPRINTF("#IGNORE for ZModem\r**\030B00");
- msleep(2000); /* let the download program start */
- /* Print 8-bpp PGM ASCII header */
- CPRINTF("P2\n%d %d\n255\n", FP_SENSOR_RES_X, FP_SENSOR_RES_Y);
-
- for (y = 0; y < FP_SENSOR_RES_Y; y++) {
- watchdog_reload();
- for (x = 0; x < FP_SENSOR_RES_X; x++, ptr++)
- CPRINTF("%d ", *ptr);
- CPRINTF("\n");
- cflush();
- }
-
- CPRINTF("\x04"); /* End Of Transmission */
-}
-
-static enum ec_error_list fp_console_action(uint32_t mode)
-{
- int tries = 200;
- uint32_t mode_output = 0;
- int rc = 0;
-
- if (!(sensor_mode & FP_MODE_RESET_SENSOR))
- CPRINTS("Waiting for finger ...");
-
- rc = fp_set_sensor_mode(mode, &mode_output);
-
- if (rc != EC_RES_SUCCESS) {
- /*
- * EC host command errors do not directly map to console command
- * errors.
- */
- return EC_ERROR_UNKNOWN;
- }
-
- while (tries--) {
- if (!(sensor_mode & FP_MODE_ANY_CAPTURE)) {
- CPRINTS("done (events:%x)", fp_events);
- return 0;
- }
- usleep(100 * MSEC);
- }
- return EC_ERROR_TIMEOUT;
-}
-
-int command_fpcapture(int argc, char **argv)
-{
- int capture_type = FP_CAPTURE_SIMPLE_IMAGE;
- uint32_t mode;
- enum ec_error_list rc;
-
- /*
- * TODO(b/142944002): Remove this redundant check for system_is_locked
- * once we have unit-tests/integration-tests in place.
- */
- if (system_is_locked())
- return EC_ERROR_ACCESS_DENIED;
-
- if (argc >= 2) {
- char *e;
-
- capture_type = strtoi(argv[1], &e, 0);
- if (*e || capture_type < 0)
- return EC_ERROR_PARAM1;
- }
- mode = FP_MODE_CAPTURE | ((capture_type << FP_MODE_CAPTURE_TYPE_SHIFT)
- & FP_MODE_CAPTURE_TYPE_MASK);
-
- rc = fp_console_action(mode);
- if (rc == EC_SUCCESS)
- upload_pgm_image(fp_buffer + FP_SENSOR_IMAGE_OFFSET);
-
- return rc;
-}
-DECLARE_CONSOLE_COMMAND_FLAGS(fpcapture, command_fpcapture, NULL,
- "Capture fingerprint in PGM format",
- CMD_FLAG_RESTRICTED);
-
-int command_fpenroll(int argc, char **argv)
-{
- enum ec_error_list rc;
- int percent = 0;
- uint32_t event;
- static const char * const enroll_str[] = {"OK", "Low Quality",
- "Immobile", "Low Coverage"};
-
- /*
- * TODO(b/142944002): Remove this redundant check for system_is_locked
- * once we have unit-tests/integration-tests in place.
- */
- if (system_is_locked())
- return EC_ERROR_ACCESS_DENIED;
-
- do {
- int tries = 1000;
-
- rc = fp_console_action(FP_MODE_ENROLL_SESSION |
- FP_MODE_ENROLL_IMAGE);
- if (rc != EC_SUCCESS)
- break;
- event = atomic_clear(&fp_events);
- percent = EC_MKBP_FP_ENROLL_PROGRESS(event);
- CPRINTS("Enroll capture: %s (%d%%)",
- enroll_str[EC_MKBP_FP_ERRCODE(event) & 3], percent);
- /* wait for finger release between captures */
- sensor_mode = FP_MODE_ENROLL_SESSION | FP_MODE_FINGER_UP;
- task_set_event(TASK_ID_FPSENSOR, TASK_EVENT_UPDATE_CONFIG);
- while (tries-- && sensor_mode & FP_MODE_FINGER_UP)
- usleep(20 * MSEC);
- } while (percent < 100);
- sensor_mode = 0; /* reset FP_MODE_ENROLL_SESSION */
- task_set_event(TASK_ID_FPSENSOR, TASK_EVENT_UPDATE_CONFIG);
-
- return rc;
-}
-DECLARE_CONSOLE_COMMAND_FLAGS(fpenroll, command_fpenroll, NULL,
- "Enroll a new fingerprint",
- CMD_FLAG_RESTRICTED);
-
-
-int command_fpmatch(int argc, char **argv)
-{
- enum ec_error_list rc = fp_console_action(FP_MODE_MATCH);
- uint32_t event = atomic_clear(&fp_events);
-
- if (rc == EC_SUCCESS && event & EC_MKBP_FP_MATCH) {
- uint32_t errcode = EC_MKBP_FP_ERRCODE(event);
-
- CPRINTS("Match: %s (%d)",
- errcode & EC_MKBP_FP_ERR_MATCH_YES ? "YES" : "NO",
- errcode);
- }
-
- return rc;
-}
-DECLARE_CONSOLE_COMMAND(fpmatch, command_fpmatch, NULL,
- "Run match algorithm against finger");
-
-int command_fpclear(int argc, char **argv)
-{
- /*
- * We intentionally run this on the fp_task so that we use the
- * same code path as host commands.
- */
- enum ec_error_list rc = fp_console_action(FP_MODE_RESET_SENSOR);
-
- if (rc < 0)
- CPRINTS("Failed to clear fingerprint context: %d", rc);
-
- atomic_clear(&fp_events);
-
- return rc;
-}
-DECLARE_CONSOLE_COMMAND(fpclear, command_fpclear, NULL,
- "Clear fingerprint sensor context");
-
-int command_fpmaintenance(int argc, char **argv)
-{
-#ifdef HAVE_FP_PRIVATE_DRIVER
- return fp_maintenance();
-#else
- return EC_SUCCESS;
-#endif /* #ifdef HAVE_FP_PRIVATE_DRIVER */
-}
-DECLARE_CONSOLE_COMMAND(fpmaintenance, command_fpmaintenance, NULL,
- "Run fingerprint sensor maintenance");
-
-#endif /* CONFIG_CMD_FPSENSOR_DEBUG */
diff --git a/common/fpsensor/fpsensor_crypto.c b/common/fpsensor/fpsensor_crypto.c
deleted file mode 100644
index 73d7aca681..0000000000
--- a/common/fpsensor/fpsensor_crypto.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/* Copyright 2019 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.
- */
-#include <stdbool.h>
-
-#include "aes.h"
-#include "aes-gcm.h"
-#include "cryptoc/util.h"
-#include "fpsensor_crypto.h"
-#include "fpsensor_private.h"
-#include "fpsensor_state.h"
-#include "rollback.h"
-
-#if !defined(CONFIG_AES) || !defined(CONFIG_AES_GCM) || \
- !defined(CONFIG_ROLLBACK_SECRET_SIZE)
-#error "fpsensor requires AES, AES_GCM and ROLLBACK_SECRET_SIZE"
-#endif
-
-static int get_ikm(uint8_t *ikm)
-{
- int ret;
-
- if (!fp_tpm_seed_is_set()) {
- CPRINTS("Seed hasn't been set.");
- return EC_ERROR_ACCESS_DENIED;
- }
-
- /*
- * The first CONFIG_ROLLBACK_SECRET_SIZE bytes of IKM are read from the
- * anti-rollback blocks.
- */
- ret = rollback_get_secret(ikm);
- if (ret != EC_SUCCESS) {
- CPRINTS("Failed to read rollback secret: %d", ret);
- return EC_ERROR_HW_INTERNAL;
- }
- /*
- * IKM is the concatenation of the rollback secret and the seed from
- * the TPM.
- */
- memcpy(ikm + CONFIG_ROLLBACK_SECRET_SIZE, tpm_seed, sizeof(tpm_seed));
-
- return EC_SUCCESS;
-}
-
-static void hkdf_extract(uint8_t *prk, const uint8_t *salt, size_t salt_size,
- const uint8_t *ikm, size_t ikm_size)
-{
- /*
- * Derive a key with the "extract" step of HKDF
- * https://tools.ietf.org/html/rfc5869#section-2.2
- */
- hmac_SHA256(prk, salt, salt_size, ikm, ikm_size);
-}
-
-static int hkdf_expand_one_step(uint8_t *out_key, size_t out_key_size,
- uint8_t *prk, size_t prk_size,
- uint8_t *info, size_t info_size)
-{
- uint8_t key_buf[SHA256_DIGEST_SIZE];
- uint8_t message_buf[SHA256_DIGEST_SIZE + 1];
-
- if (out_key_size > SHA256_DIGEST_SIZE) {
- CPRINTS("Deriving key material longer than SHA256_DIGEST_SIZE "
- "requires more steps of HKDF expand.");
- return EC_ERROR_INVAL;
- }
-
- if (info_size > SHA256_DIGEST_SIZE) {
- CPRINTS("Info size too big for HKDF.");
- return EC_ERROR_INVAL;
- }
-
- memcpy(message_buf, info, info_size);
- /* 1 step, set the counter byte to 1. */
- message_buf[info_size] = 0x01;
- hmac_SHA256(key_buf, prk, prk_size, message_buf, info_size + 1);
-
- memcpy(out_key, key_buf, out_key_size);
- always_memset(key_buf, 0, sizeof(key_buf));
-
- return EC_SUCCESS;
-}
-
-int hkdf_expand(uint8_t *out_key, size_t L, const uint8_t *prk,
- size_t prk_size, const uint8_t *info, size_t info_size)
-{
- /*
- * "Expand" step of HKDF.
- * https://tools.ietf.org/html/rfc5869#section-2.3
- */
-#define HASH_LEN SHA256_DIGEST_SIZE
- uint8_t count = 1;
- const uint8_t *T = out_key;
- size_t T_len = 0;
- uint8_t T_buffer[HASH_LEN];
- /* Number of blocks. */
- const uint32_t N = DIV_ROUND_UP(L, HASH_LEN);
- uint8_t info_buffer[HASH_LEN + HKDF_MAX_INFO_SIZE + sizeof(count)];
- bool arguments_valid = false;
-
- if (out_key == NULL || L == 0)
- CPRINTS("HKDF expand: output buffer not valid.");
- else if (prk == NULL)
- CPRINTS("HKDF expand: prk is NULL.");
- else if (info == NULL && info_size > 0)
- CPRINTS("HKDF expand: info is NULL but info size is not zero.");
- else if (info_size > HKDF_MAX_INFO_SIZE)
- CPRINTF("HKDF expand: info size larger than %d bytes.\n",
- HKDF_MAX_INFO_SIZE);
- else if (N > HKDF_SHA256_MAX_BLOCK_COUNT)
- CPRINTS("HKDF expand: output key size too large.");
- else
- arguments_valid = true;
-
- if (!arguments_valid)
- return EC_ERROR_INVAL;
-
- while (L > 0) {
- const size_t block_size = L < HASH_LEN ? L : HASH_LEN;
-
- memcpy(info_buffer, T, T_len);
- memcpy(info_buffer + T_len, info, info_size);
- info_buffer[T_len + info_size] = count;
- hmac_SHA256(T_buffer, prk, prk_size, info_buffer,
- T_len + info_size + sizeof(count));
- memcpy(out_key, T_buffer, block_size);
-
- T += T_len;
- T_len = HASH_LEN;
- count++;
- out_key += block_size;
- L -= block_size;
- }
- always_memset(T_buffer, 0, sizeof(T_buffer));
- always_memset(info_buffer, 0, sizeof(info_buffer));
- return EC_SUCCESS;
-#undef HASH_LEN
-}
-
-int derive_positive_match_secret(uint8_t *output,
- const uint8_t *input_positive_match_salt)
-{
- int ret;
- uint8_t ikm[CONFIG_ROLLBACK_SECRET_SIZE + sizeof(tpm_seed)];
- uint8_t prk[SHA256_DIGEST_SIZE];
- static const char info_prefix[] = "positive_match_secret for user ";
- uint8_t info[sizeof(info_prefix) - 1 + sizeof(user_id)];
-
- if (bytes_are_trivial(input_positive_match_salt,
- FP_POSITIVE_MATCH_SALT_BYTES)) {
- CPRINTS("Failed to derive positive match secret: "
- "salt bytes are trivial.");
- return EC_ERROR_INVAL;
- }
-
- ret = get_ikm(ikm);
- if (ret != EC_SUCCESS) {
- CPRINTS("Failed to get IKM: %d", ret);
- return ret;
- }
-
- /* "Extract" step of HKDF. */
- hkdf_extract(prk, input_positive_match_salt,
- FP_POSITIVE_MATCH_SALT_BYTES, ikm, sizeof(ikm));
- always_memset(ikm, 0, sizeof(ikm));
-
- memcpy(info, info_prefix, strlen(info_prefix));
- memcpy(info + strlen(info_prefix), user_id, sizeof(user_id));
-
- /* "Expand" step of HKDF. */
- ret = hkdf_expand(output, FP_POSITIVE_MATCH_SECRET_BYTES, prk,
- sizeof(prk), info, sizeof(info));
- always_memset(prk, 0, sizeof(prk));
-
- /* Check that secret is not full of 0x00 or 0xff. */
- if (bytes_are_trivial(output, FP_POSITIVE_MATCH_SECRET_BYTES)) {
- CPRINTS("Failed to derive positive match secret: "
- "derived secret bytes are trivial.");
- ret = EC_ERROR_HW_INTERNAL;
- }
- return ret;
-}
-
-int derive_encryption_key(uint8_t *out_key, const uint8_t *salt)
-{
- int ret;
- uint8_t ikm[CONFIG_ROLLBACK_SECRET_SIZE + sizeof(tpm_seed)];
- uint8_t prk[SHA256_DIGEST_SIZE];
-
- BUILD_ASSERT(SBP_ENC_KEY_LEN <= SHA256_DIGEST_SIZE);
- BUILD_ASSERT(SBP_ENC_KEY_LEN <= CONFIG_ROLLBACK_SECRET_SIZE);
- BUILD_ASSERT(sizeof(user_id) == SHA256_DIGEST_SIZE);
-
- ret = get_ikm(ikm);
- if (ret != EC_SUCCESS) {
- CPRINTS("Failed to get IKM: %d", ret);
- return ret;
- }
-
- /* "Extract step of HKDF. */
- hkdf_extract(prk, salt, FP_CONTEXT_ENCRYPTION_SALT_BYTES, ikm,
- sizeof(ikm));
- always_memset(ikm, 0, sizeof(ikm));
-
- /*
- * Only 1 "expand" step of HKDF since the size of the "info" context
- * (user_id in our case) is exactly SHA256_DIGEST_SIZE.
- * https://tools.ietf.org/html/rfc5869#section-2.3
- */
- ret = hkdf_expand_one_step(out_key, SBP_ENC_KEY_LEN, prk, sizeof(prk),
- (uint8_t *)user_id, sizeof(user_id));
- always_memset(prk, 0, sizeof(prk));
-
- return ret;
-}
-
-int aes_gcm_encrypt(const uint8_t *key, int key_size,
- const uint8_t *plaintext,
- uint8_t *ciphertext, int text_size,
- const uint8_t *nonce, int nonce_size,
- uint8_t *tag, int tag_size)
-{
- int res;
- AES_KEY aes_key;
- GCM128_CONTEXT ctx;
-
- if (nonce_size != FP_CONTEXT_NONCE_BYTES) {
- CPRINTS("Invalid nonce size %d bytes", nonce_size);
- return EC_ERROR_INVAL;
- }
-
- res = AES_set_encrypt_key(key, 8 * key_size, &aes_key);
- if (res) {
- CPRINTS("Failed to set encryption key: %d", res);
- return EC_ERROR_UNKNOWN;
- }
- CRYPTO_gcm128_init(&ctx, &aes_key, (block128_f)AES_encrypt, 0);
- CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce, nonce_size);
- /* CRYPTO functions return 1 on success, 0 on error. */
- res = CRYPTO_gcm128_encrypt(&ctx, &aes_key, plaintext, ciphertext,
- text_size);
- if (!res) {
- CPRINTS("Failed to encrypt: %d", res);
- return EC_ERROR_UNKNOWN;
- }
- CRYPTO_gcm128_tag(&ctx, tag, tag_size);
- return EC_SUCCESS;
-}
-
-int aes_gcm_decrypt(const uint8_t *key, int key_size, uint8_t *plaintext,
- const uint8_t *ciphertext, int text_size,
- const uint8_t *nonce, int nonce_size,
- const uint8_t *tag, int tag_size)
-{
- int res;
- AES_KEY aes_key;
- GCM128_CONTEXT ctx;
-
- if (nonce_size != FP_CONTEXT_NONCE_BYTES) {
- CPRINTS("Invalid nonce size %d bytes", nonce_size);
- return EC_ERROR_INVAL;
- }
-
- res = AES_set_encrypt_key(key, 8 * key_size, &aes_key);
- if (res) {
- CPRINTS("Failed to set decryption key: %d", res);
- return EC_ERROR_UNKNOWN;
- }
- CRYPTO_gcm128_init(&ctx, &aes_key, (block128_f)AES_encrypt, 0);
- CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce, nonce_size);
- /* CRYPTO functions return 1 on success, 0 on error. */
- res = CRYPTO_gcm128_decrypt(&ctx, &aes_key, ciphertext, plaintext,
- text_size);
- if (!res) {
- CPRINTS("Failed to decrypt: %d", res);
- return EC_ERROR_UNKNOWN;
- }
- res = CRYPTO_gcm128_finish(&ctx, tag, tag_size);
- if (!res) {
- CPRINTS("Found incorrect tag: %d", res);
- return EC_ERROR_UNKNOWN;
- }
- return EC_SUCCESS;
-}
diff --git a/common/fpsensor/fpsensor_private.h b/common/fpsensor/fpsensor_private.h
deleted file mode 100644
index a42049dece..0000000000
--- a/common/fpsensor/fpsensor_private.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright 2019 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.
- */
-
-/* Internal header file for common/fpsensor directory */
-
-#ifndef __CROS_EC_FPSENSOR_PRIVATE_H
-#define __CROS_EC_FPSENSOR_PRIVATE_H
-
-#include <stdint.h>
-
-#define CPRINTF(format, args...) cprintf(CC_FP, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_FP, format, ## args)
-
-int validate_fp_buffer_offset(uint32_t buffer_size, uint32_t offset,
- uint32_t size);
-
-#endif /* __CROS_EC_FPSENSOR_PRIVATE_H */
diff --git a/common/fpsensor/fpsensor_state.c b/common/fpsensor/fpsensor_state.c
deleted file mode 100644
index db64110b56..0000000000
--- a/common/fpsensor/fpsensor_state.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/* Copyright 2019 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.
- */
-
-#include "common.h"
-#include "cryptoc/util.h"
-#include "ec_commands.h"
-#include "fpsensor.h"
-#include "fpsensor_crypto.h"
-#include "fpsensor_private.h"
-#include "fpsensor_state.h"
-#include "host_command.h"
-#include "system.h"
-#include "task.h"
-#include "util.h"
-
-/* Last acquired frame (aligned as it is used by arbitrary binary libraries) */
-uint8_t fp_buffer[FP_SENSOR_IMAGE_SIZE] FP_FRAME_SECTION __aligned(4);
-/* Fingers templates for the current user */
-uint8_t fp_template[FP_MAX_FINGER_COUNT][FP_ALGORITHM_TEMPLATE_SIZE]
- FP_TEMPLATE_SECTION;
-/* Encryption/decryption buffer */
-/* TODO: On-the-fly encryption/decryption without a dedicated buffer */
-/*
- * Store the encryption metadata at the beginning of the buffer containing the
- * ciphered data.
- */
-uint8_t fp_enc_buffer[FP_ALGORITHM_ENCRYPTED_TEMPLATE_SIZE]
- FP_TEMPLATE_SECTION;
-/* Salt used in derivation of positive match secret. */
-uint8_t fp_positive_match_salt
- [FP_MAX_FINGER_COUNT][FP_POSITIVE_MATCH_SALT_BYTES];
-
-struct positive_match_secret_state positive_match_secret_state = {
- .template_matched = FP_NO_SUCH_TEMPLATE,
- .readable = false,
- .deadline.val = 0,
-};
-
-/* Index of the last enrolled but not retrieved template. */
-int8_t template_newly_enrolled = FP_NO_SUCH_TEMPLATE;
-/* Number of used templates */
-uint32_t templ_valid;
-/* Bitmap of the templates with local modifications */
-uint32_t templ_dirty;
-/* Current user ID */
-uint32_t user_id[FP_CONTEXT_USERID_WORDS];
-/* Part of the IKM used to derive encryption keys received from the TPM. */
-uint8_t tpm_seed[FP_CONTEXT_TPM_BYTES];
-/* Status of the FP encryption engine. */
-static uint32_t fp_encryption_status;
-
-uint32_t fp_events;
-
-uint32_t sensor_mode;
-
-void fp_task_simulate(void)
-{
- int timeout_us = -1;
-
- while (1)
- task_wait_event(timeout_us);
-}
-
-void fp_clear_finger_context(int idx)
-{
- always_memset(fp_template[idx], 0, sizeof(fp_template[0]));
- always_memset(fp_positive_match_salt[idx], 0,
- sizeof(fp_positive_match_salt[0]));
-}
-
-/**
- * @warning |fp_buffer| contains data used by the matching algorithm that must
- * be released by calling fp_sensor_deinit() first. Call
- * fp_reset_and_clear_context instead of calling this directly.
- */
-static void _fp_clear_context(void)
-{
- int idx;
-
- templ_valid = 0;
- templ_dirty = 0;
- always_memset(fp_buffer, 0, sizeof(fp_buffer));
- always_memset(fp_enc_buffer, 0, sizeof(fp_enc_buffer));
- always_memset(user_id, 0, sizeof(user_id));
- fp_disable_positive_match_secret(&positive_match_secret_state);
- for (idx = 0; idx < FP_MAX_FINGER_COUNT; idx++)
- fp_clear_finger_context(idx);
-}
-
-void fp_reset_and_clear_context(void)
-{
- if (fp_sensor_deinit() != EC_SUCCESS)
- CPRINTS("Failed to deinit sensor");
- _fp_clear_context();
- if (fp_sensor_init() != EC_SUCCESS)
- CPRINTS("Failed to init sensor");
-}
-
-int fp_get_next_event(uint8_t *out)
-{
- uint32_t event_out = atomic_clear(&fp_events);
-
- memcpy(out, &event_out, sizeof(event_out));
-
- return sizeof(event_out);
-}
-DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_FINGERPRINT, fp_get_next_event);
-
-static enum ec_status fp_command_tpm_seed(struct host_cmd_handler_args *args)
-{
- const struct ec_params_fp_seed *params = args->params;
-
- if (params->struct_version != FP_TEMPLATE_FORMAT_VERSION) {
- CPRINTS("Invalid seed format %d", params->struct_version);
- return EC_RES_INVALID_PARAM;
- }
-
- if (fp_encryption_status & FP_ENC_STATUS_SEED_SET) {
- CPRINTS("Seed has already been set.");
- return EC_RES_ACCESS_DENIED;
- }
- memcpy(tpm_seed, params->seed, sizeof(tpm_seed));
- fp_encryption_status |= FP_ENC_STATUS_SEED_SET;
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_FP_SEED, fp_command_tpm_seed, EC_VER_MASK(0));
-
-int fp_tpm_seed_is_set(void)
-{
- return fp_encryption_status & FP_ENC_STATUS_SEED_SET;
-}
-
-static enum ec_status
-fp_command_encryption_status(struct host_cmd_handler_args *args)
-{
- struct ec_response_fp_encryption_status *r = args->response;
-
- r->valid_flags = FP_ENC_STATUS_SEED_SET;
- r->status = fp_encryption_status;
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_FP_ENC_STATUS, fp_command_encryption_status,
- EC_VER_MASK(0));
-
-static int validate_fp_mode(const uint32_t mode)
-{
- uint32_t capture_type = FP_CAPTURE_TYPE(mode);
- uint32_t algo_mode = mode & ~FP_MODE_CAPTURE_TYPE_MASK;
- uint32_t cur_mode = sensor_mode;
-
- if (capture_type >= FP_CAPTURE_TYPE_MAX)
- return EC_ERROR_INVAL;
-
- if (algo_mode & ~FP_VALID_MODES)
- return EC_ERROR_INVAL;
-
- if ((mode & FP_MODE_ENROLL_SESSION) &&
- templ_valid >= FP_MAX_FINGER_COUNT) {
- CPRINTS("Maximum number of fingers already enrolled: %d",
- FP_MAX_FINGER_COUNT);
- return EC_ERROR_INVAL;
- }
-
- /* Don't allow sensor reset if any other mode is
- * set (including FP_MODE_RESET_SENSOR itself).
- */
- if (mode & FP_MODE_RESET_SENSOR) {
- if (cur_mode & FP_VALID_MODES)
- return EC_ERROR_INVAL;
- }
-
- return EC_SUCCESS;
-}
-
-int fp_set_sensor_mode(uint32_t mode, uint32_t *mode_output)
-{
- int ret;
-
- if (mode_output == NULL)
- return EC_RES_INVALID_PARAM;
-
- ret = validate_fp_mode(mode);
- if (ret != EC_SUCCESS) {
- CPRINTS("Invalid FP mode 0x%x", mode);
- return EC_RES_INVALID_PARAM;
- }
-
- if (!(mode & FP_MODE_DONT_CHANGE)) {
- sensor_mode = mode;
- task_set_event(TASK_ID_FPSENSOR, TASK_EVENT_UPDATE_CONFIG);
- }
-
- *mode_output = sensor_mode;
- return EC_RES_SUCCESS;
-}
-
-static enum ec_status fp_command_mode(struct host_cmd_handler_args *args)
-{
- const struct ec_params_fp_mode *p = args->params;
- struct ec_response_fp_mode *r = args->response;
-
- int ret = fp_set_sensor_mode(p->mode, &r->mode);
-
- if (ret == EC_RES_SUCCESS)
- args->response_size = sizeof(*r);
-
- return ret;
-}
-DECLARE_HOST_COMMAND(EC_CMD_FP_MODE, fp_command_mode, EC_VER_MASK(0));
-
-static enum ec_status fp_command_context(struct host_cmd_handler_args *args)
-{
- const struct ec_params_fp_context_v1 *p = args->params;
- uint32_t mode_output;
-
- switch (p->action) {
- case FP_CONTEXT_ASYNC:
- if (sensor_mode & FP_MODE_RESET_SENSOR)
- return EC_RES_BUSY;
-
- /**
- * Trigger a call to fp_reset_and_clear_context() by
- * requesting a reset. Since that function triggers a call to
- * fp_sensor_open(), this must be asynchronous because
- * fp_sensor_open() can take ~175 ms. See http://b/137288498.
- */
- return fp_set_sensor_mode(FP_MODE_RESET_SENSOR, &mode_output);
-
- case FP_CONTEXT_GET_RESULT:
- if (sensor_mode & FP_MODE_RESET_SENSOR)
- return EC_RES_BUSY;
-
- memcpy(user_id, p->userid, sizeof(user_id));
- return EC_RES_SUCCESS;
- }
-
- return EC_RES_INVALID_PARAM;
-}
-DECLARE_HOST_COMMAND(EC_CMD_FP_CONTEXT, fp_command_context, EC_VER_MASK(1));
-
-int fp_enable_positive_match_secret(uint32_t fgr,
- struct positive_match_secret_state *state)
-{
- timestamp_t now;
-
- if (state->readable) {
- CPRINTS("Error: positive match secret already readable.");
- fp_disable_positive_match_secret(state);
- return EC_ERROR_UNKNOWN;
- }
-
- now = get_time();
- state->template_matched = fgr;
- state->readable = true;
- state->deadline.val = now.val + (5 * SECOND);
- return EC_SUCCESS;
-}
-
-void fp_disable_positive_match_secret(
- struct positive_match_secret_state *state)
-{
- state->template_matched = FP_NO_SUCH_TEMPLATE;
- state->readable = false;
- state->deadline.val = 0;
-}
-
-static enum ec_status fp_command_read_match_secret(
- struct host_cmd_handler_args *args)
-{
- const struct ec_params_fp_read_match_secret *params = args->params;
- struct ec_response_fp_read_match_secret *response = args->response;
- int8_t fgr = params->fgr;
- timestamp_t now = get_time();
- struct positive_match_secret_state state_copy
- = positive_match_secret_state;
-
- fp_disable_positive_match_secret(&positive_match_secret_state);
-
- if (fgr < 0 || fgr >= FP_MAX_FINGER_COUNT) {
- CPRINTS("Invalid finger number %d", fgr);
- return EC_RES_INVALID_PARAM;
- }
- if (timestamp_expired(state_copy.deadline, &now)) {
- CPRINTS("Reading positive match secret disallowed: "
- "deadline has passed.");
- return EC_RES_TIMEOUT;
- }
- if (fgr != state_copy.template_matched || !state_copy.readable) {
- CPRINTS("Positive match secret for finger %d is not meant to "
- "be read now.", fgr);
- return EC_RES_ACCESS_DENIED;
- }
-
- if (derive_positive_match_secret(response->positive_match_secret,
- fp_positive_match_salt[fgr])
- != EC_SUCCESS) {
- CPRINTS("Failed to derive positive match secret for finger %d",
- fgr);
- /* Keep the template and encryption salt. */
- return EC_RES_ERROR;
- }
- CPRINTS("Derived positive match secret for finger %d", fgr);
- args->response_size = sizeof(*response);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_FP_READ_MATCH_SECRET, fp_command_read_match_secret,
- EC_VER_MASK(0));
diff --git a/common/gesture.c b/common/gesture.c
deleted file mode 100644
index 88d79448a5..0000000000
--- a/common/gesture.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/* Copyright 2014 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.
- */
-
-/* Board specific gesture recognition */
-
-#include "accelgyro.h"
-#include "common.h"
-#include "console.h"
-#include "hooks.h"
-#include "gesture.h"
-#include "lid_switch.h"
-#include "lightbar.h"
-#include "motion_sense.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_GESTURE, outstr)
-#define CPRINTS(format, args...) cprints(CC_GESTURE, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_GESTURE, format, ## args)
-
-
-/*
- * Double tap detection parameters
- * Double tap works by looking for two isolated Z-axis accelerometer impulses
- * preceded and followed by relatively calm periods of accelerometer motion.
- *
- * Define an outer and inner window. The inner window specifies how
- * long the tap impulse is expected to last. The outer window specifies the
- * period before the initial tap impluse and after the final tap impulse for
- * which to check for relatively calm periods. In between the two impulses
- * there is a minimum and maximum interstice time allowed.
- */
-#define OUTER_WINDOW \
- (CONFIG_GESTURE_TAP_OUTER_WINDOW_T / \
- CONFIG_GESTURE_SAMPLING_INTERVAL_MS)
-#define INNER_WINDOW \
- (CONFIG_GESTURE_TAP_INNER_WINDOW_T / \
- CONFIG_GESTURE_SAMPLING_INTERVAL_MS)
-#define MIN_INTERSTICE \
- (CONFIG_GESTURE_TAP_MIN_INTERSTICE_T / \
- CONFIG_GESTURE_SAMPLING_INTERVAL_MS)
-#define MAX_INTERSTICE \
- (CONFIG_GESTURE_TAP_MAX_INTERSTICE_T / \
- CONFIG_GESTURE_SAMPLING_INTERVAL_MS)
-#define MAX_WINDOW OUTER_WINDOW
-
-/* State machine states for detecting double tap */
-enum tap_states {
- /* Look for calm before the storm */
- TAP_IDLE,
- /* Record first Z impulse */
- TAP_IMPULSE_1,
-
- /* Eye of the storm, expect Z motion to drop and then suddenly spike */
- TAP_INTERSTICE_DROP,
- TAP_INTERSTICE_RISE,
-
- /* Record second Z impulse */
- TAP_IMPULSE_2,
- /* Should be quiet after the storm */
- TAP_AFTER_EVENT
-};
-
-/* Tap sensor to use */
-static struct motion_sensor_t *sensor =
-&motion_sensors[CONFIG_GESTURE_TAP_SENSOR];
-
-/* Tap state information */
-static int history_z[MAX_WINDOW]; /* Changes in Z */
-static int history_xy[MAX_WINDOW]; /* Changes in X and Y */
-static int state, history_idx;
-static int history_initialized, history_init_index;
-static int tap_debug;
-
-/* Tap detection flag */
-static int tap_detection;
-
-/*
- * TODO(crosbug.com/p/33102): Cleanup this function: break into multiple
- * functions and generalize so it can be used for other boards.
- */
-static int gesture_tap_for_battery(void)
-{
- /* Current and previous accel x,y,z */
- int x, y, z;
- static int x_p, y_p, z_p;
-
- /* Number of iterations in this state */
- static int state_cnt;
-
- /*
- * Running sums of data diffs for inner and outer windows.
- * Z data kept separate from X and Y data
- */
- static int sum_z_inner, sum_z_outer, sum_xy_inner, sum_xy_outer;
-
- /* Total variation in each signal, normalized for window size */
- int delta_z_outer, delta_z_inner, delta_xy_outer, delta_xy_inner;
-
- /* Max variation seen during tap event and state cnts since max */
- static int delta_z_inner_max;
- static int cnts_since_max;
-
- /* Interstice Z motion thresholds */
- static int z_drop_thresh, z_rise_thresh;
-
- int history_idx_inner, state_p;
- int ret = 0;
-
- /* Get data */
- x = sensor->xyz[0];
- y = sensor->xyz[1];
- z = sensor->xyz[2];
-
- /*
- * Calculate history of change in Z sensor and keeping
- * running sums for the past.
- */
- history_idx_inner = history_idx - INNER_WINDOW;
- if (history_idx_inner < 0)
- history_idx_inner += MAX_WINDOW;
- sum_z_inner -= history_z[history_idx_inner];
- sum_z_outer -= history_z[history_idx];
- history_z[history_idx] = ABS(z - z_p);
- sum_z_inner += history_z[history_idx];
- sum_z_outer += history_z[history_idx];
-
- /*
- * Calculate history of change in X and Y sensors combined
- * and keep a running sum of the change over the past.
- */
- sum_xy_inner -= history_xy[history_idx_inner];
- sum_xy_outer -= history_xy[history_idx];
- history_xy[history_idx] = ABS(x - x_p) + ABS(y - y_p);
- sum_xy_inner += history_xy[history_idx];
- sum_xy_outer += history_xy[history_idx];
-
- /* Increment history index */
- history_idx = (history_idx == MAX_WINDOW - 1) ? 0 : (history_idx + 1);
-
- /* Store previous X, Y, Z data */
- x_p = x;
- y_p = y;
- z_p = z;
-
- /*
- * Ignore data until we fill history buffer and wrap around. If
- * detection is paused, history_init_index will store the index
- * when paused, so that when re-started, we will wait until we
- * wrap around again.
- */
- if (history_idx == history_init_index)
- history_initialized = 1;
- if (!history_initialized)
- return 0;
-
- /*
- * Normalize data based on window size and isolate outer and inner
- * window data.
- */
- delta_z_outer = (sum_z_outer - sum_z_inner) * 1000 /
- (OUTER_WINDOW - INNER_WINDOW);
- delta_z_inner = sum_z_inner * 1000 / INNER_WINDOW;
- delta_xy_outer = (sum_xy_outer - sum_xy_inner) * 1000 /
- (OUTER_WINDOW - INNER_WINDOW);
- delta_xy_inner = sum_xy_inner * 1000 / INNER_WINDOW;
-
- state_cnt++;
- state_p = state;
-
- switch (state) {
- case TAP_IDLE:
- /* Look for a sudden increase in Z movement */
- if (delta_z_inner > 30000 &&
- delta_z_inner > 13 * delta_z_outer &&
- delta_z_inner > 1 * delta_xy_inner) {
- delta_z_inner_max = delta_z_inner;
- state_cnt = 0;
- state = TAP_IMPULSE_1;
- }
- break;
-
- case TAP_IMPULSE_1:
- /* Find the peak inner window of Z movement */
- if (delta_z_inner > delta_z_inner_max) {
- delta_z_inner_max = delta_z_inner;
- cnts_since_max = state_cnt;
- }
-
- /* After inner window has passed, move to next state */
- if (state_cnt >= INNER_WINDOW) {
- state = TAP_INTERSTICE_DROP;
- z_drop_thresh = delta_z_inner_max / 12;
- z_rise_thresh = delta_z_inner_max / 3;
- state_cnt += INNER_WINDOW - cnts_since_max;
- }
- break;
-
- case TAP_INTERSTICE_DROP:
- /* Check for z motion to go back down first */
- if (delta_z_inner < z_drop_thresh)
- state = TAP_INTERSTICE_RISE;
-
- if (state_cnt > MAX_INTERSTICE)
- state = TAP_IDLE;
-
- break;
-
- case TAP_INTERSTICE_RISE:
- /* Then, check for z motion to go back up */
- if (delta_z_inner > z_rise_thresh) {
- if (state_cnt < MIN_INTERSTICE) {
- state = TAP_IDLE;
- } else {
- delta_z_inner_max = delta_z_inner;
- state_cnt = 0;
- state = TAP_IMPULSE_2;
- }
- }
-
- if (state_cnt > MAX_INTERSTICE)
- state = TAP_IDLE;
- break;
-
- case TAP_IMPULSE_2:
- /* Find the peak inner window of Z movement */
- if (delta_z_inner > delta_z_inner_max) {
- delta_z_inner_max = delta_z_inner;
- cnts_since_max = state_cnt;
- }
-
- /* After inner window has passed, move to next state */
- if (state_cnt >= INNER_WINDOW) {
- state = TAP_AFTER_EVENT;
- state_cnt += INNER_WINDOW - cnts_since_max;
- }
-
- case TAP_AFTER_EVENT:
- /* Check for small Z movement after the event */
- if (state_cnt < OUTER_WINDOW)
- break;
-
- if (2 * delta_z_inner_max > 3 * delta_z_outer &&
- delta_z_outer > 1 * delta_xy_outer)
- ret = 1;
-
- state = TAP_IDLE;
- break;
- }
-
- /* On state transitions, print debug info */
- if (tap_debug &&
- (state != state_p ||
- (state_cnt % 10000 == 9999))) {
- /* make sure we don't divide by 0 */
- if (delta_z_outer == 0 || delta_xy_inner == 0)
- CPRINTS("tap st %d->%d, error div by 0",
- state_p, state);
- else
- CPRINTS("tap st %d->%d, st_cnt %-3d "
- "Z_in:Z_out %-3d, Z_in:XY_in %-3d "
- "dZ_in %-8.3d, dZ_in_max %-8.3d, "
- "dZ_out %-8.3d",
- state_p, state, state_cnt,
- delta_z_inner / delta_z_outer,
- delta_z_inner / delta_xy_inner,
- delta_z_inner,
- delta_z_inner_max,
- delta_z_outer);
- }
-
- return ret;
-}
-
-static void gesture_chipset_resume(void)
-{
- /* disable tap detection */
- tap_detection = 0;
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, gesture_chipset_resume,
- GESTURE_HOOK_PRIO);
-
-static void gesture_chipset_suspend(void)
-{
- /*
- * Clear tap init and history initialized so that we have to
- * record a whole new set of data, and enable tap detection
- */
- history_initialized = 0;
- history_init_index = history_idx;
- state = TAP_IDLE;
- tap_detection = 1;
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, gesture_chipset_suspend,
- GESTURE_HOOK_PRIO);
-
-void gesture_calc(uint32_t *event)
-{
- /* Only check for gesture if lid is closed and tap detection is on */
- if (!tap_detection || lid_is_open())
- return;
-
- if (gesture_tap_for_battery())
- *event |= TASK_EVENT_MOTION_ACTIVITY_INTERRUPT(
- MOTIONSENSE_ACTIVITY_DOUBLE_TAP);
-}
-
-/*****************************************************************************/
-/* Console commands */
-static int command_tap_info(int argc, char **argv)
-{
- int val;
-
- ccprintf("tap: %s\n", (tap_detection && !lid_is_open()) ?
- "on" : "off");
-
- if (argc > 1) {
- if (!parse_bool(argv[1], &val))
- return EC_ERROR_PARAM1;
- tap_debug = val;
- }
-
- ccprintf("debug: %s\n", tap_debug ? "on" : "off");
- ccprintf("odr: %d\n", sensor->drv->get_data_rate(sensor));
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(tapinfo, command_tap_info,
- "debug on/off",
- "Print tap information");
-
diff --git a/common/gyro_cal.c b/common/gyro_cal.c
deleted file mode 100644
index 572e401b18..0000000000
--- a/common/gyro_cal.c
+++ /dev/null
@@ -1,630 +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.
- */
-
-#include "gyro_cal.h"
-#include "string.h"
-#include <stdbool.h>
-
-/*
- * Maximum gyro bias correction (should be set based on expected max bias
- * of the given sensor). [rad/sec]
- */
-#define MAX_GYRO_BIAS FLOAT_TO_FP(0.2f)
-
-static void device_stillness_check(struct gyro_cal *gyro_cal,
- uint32_t sample_time_us);
-
-static void compute_gyro_cal(struct gyro_cal *gyro_cal,
- uint32_t calibration_time_us);
-
-static void check_window(struct gyro_cal *gyro_cal, uint32_t sample_time_us);
-
-/** Data tracker command enumeration. */
-enum gyro_cal_tracker_command {
- /** Resets the local data used for data tracking. */
- DO_RESET = 0,
- /** Updates the local tracking data. */
- DO_UPDATE_DATA,
- /** Stores intermediate results for later recall. */
- DO_STORE_DATA,
- /** Computes and provides the results of the gate function. */
- DO_EVALUATE
-};
-
-/**
- * Reset the gyro_cal's temperature statistics.
- *
- * @param gyro_cal Pointer to the gyro_cal data structure.
- */
-static void gyro_temperature_stats_tracker_reset(struct gyro_cal *gyro_cal);
-
-/**
- * Updates the temperature min/max and mean during the stillness period.
- *
- * @param gyro_cal Pointer to the gyro_cal data structure.
- * @param temperature_kelvin New temperature sample to include.
- */
-static void gyro_temperature_stats_tracker_update(struct gyro_cal *gyro_cal,
- int temperature_kelvin);
-
-/**
- * Store the tracker data to be used for calculation.
- *
- * @param gyro_cal Pointer to the gyro_cal data structure.
- */
-static void gyro_temperature_stats_tracker_store(struct gyro_cal *gyro_cal);
-
-/**
- * Compute whether or not the temperature values are in range.
- *
- * @param gyro_cal Pointer to the gyro_cal data structure.
- * @return 'true' if the min and max temperature values exceed the
- * range set by 'temperature_delta_limit_kelvin'.
- */
-static bool gyro_temperature_stats_tracker_eval(struct gyro_cal *gyro_cal);
-
-/**
- * Tracks the minimum and maximum gyroscope stillness window means.
- * Returns
- *
- * @param gyro_cal Pointer to the gyro_cal data structure.
- * @param do_this Command enumerator that controls function behavior.
- */
-static void gyro_still_mean_tracker_reset(struct gyro_cal *gyro_cal);
-
-/**
- * Compute the min/max window mean values according to 'window_mean_tracker'.
- *
- * @param gyro_cal Pointer to the gyro_cal data structure.
- */
-static void gyro_still_mean_tracker_update(struct gyro_cal *gyro_cal);
-
-/**
- * Store the most recent "stillness" mean data to the gyro_cal data structure.
- *
- * @param gyro_cal Pointer to the gyro_cal data structure.
- */
-static void gyro_still_mean_tracker_store(struct gyro_cal *gyro_cal);
-
-/**
- * Compute whether or not the gyroscope window range is within the valid range.
- *
- * @param gyro_cal Pointer to the gyro_cal data structure.
- * @return 'true' when the difference between gyroscope min and max
- * window means are outside the range set by
- * 'stillness_mean_delta_limit'.
- */
-static bool gyro_still_mean_tracker_eval(struct gyro_cal *gyro_cal);
-
-void init_gyro_cal(struct gyro_cal *gyro_cal)
-{
- gyro_still_mean_tracker_reset(gyro_cal);
- gyro_temperature_stats_tracker_reset(gyro_cal);
-}
-
-void gyro_cal_get_bias(struct gyro_cal *gyro_cal, fpv3_t bias,
- int *temperature_kelvin, uint32_t *calibration_time_us)
-{
- bias[X] = gyro_cal->bias_x;
- bias[Y] = gyro_cal->bias_y;
- bias[Z] = gyro_cal->bias_z;
- *calibration_time_us = gyro_cal->calibration_time_us;
- *temperature_kelvin = gyro_cal->bias_temperature_kelvin;
-}
-
-void gyro_cal_set_bias(struct gyro_cal *gyro_cal, fpv3_t bias,
- int temperature_kelvin, uint32_t calibration_time_us)
-{
- gyro_cal->bias_x = bias[X];
- gyro_cal->bias_y = bias[Y];
- gyro_cal->bias_z = bias[Z];
- gyro_cal->calibration_time_us = calibration_time_us;
- gyro_cal->bias_temperature_kelvin = temperature_kelvin;
-}
-
-void gyro_cal_remove_bias(struct gyro_cal *gyro_cal, fpv3_t in, fpv3_t out)
-{
- if (gyro_cal->gyro_calibration_enable) {
- out[X] = in[X] - gyro_cal->bias_x;
- out[Y] = in[Y] - gyro_cal->bias_y;
- out[Z] = in[Z] - gyro_cal->bias_z;
- }
-}
-
-bool gyro_cal_new_bias_available(struct gyro_cal *gyro_cal)
-{
- bool new_gyro_cal_available = (gyro_cal->gyro_calibration_enable &&
- gyro_cal->new_gyro_cal_available);
-
- /* Clear the flag. */
- gyro_cal->new_gyro_cal_available = false;
-
- return new_gyro_cal_available;
-}
-
-void gyro_cal_update_gyro(struct gyro_cal *gyro_cal, uint32_t sample_time_us,
- fp_t x, fp_t y, fp_t z, int temperature_kelvin)
-{
- /*
- * Make sure that a valid window end-time is set, and start the window
- * timer.
- */
- if (gyro_cal->stillness_win_endtime_us <= 0) {
- gyro_cal->stillness_win_endtime_us =
- sample_time_us + gyro_cal->window_time_duration_us;
-
- /* Start the window timer. */
- gyro_cal->gyro_window_start_us = sample_time_us;
- }
-
- /* Update the temperature statistics. */
- gyro_temperature_stats_tracker_update(gyro_cal, temperature_kelvin);
-
- /* Pass gyro data to stillness detector */
- gyro_still_det_update(&gyro_cal->gyro_stillness_detect,
- gyro_cal->stillness_win_endtime_us,
- sample_time_us, x, y, z);
-
- /*
- * Perform a device stillness check, set next window end-time, and
- * possibly do a gyro bias calibration and stillness detector reset.
- */
- device_stillness_check(gyro_cal, sample_time_us);
-}
-
-void gyro_cal_update_mag(struct gyro_cal *gyro_cal, uint32_t sample_time_us,
- fp_t x, fp_t y, fp_t z)
-{
- /* Pass magnetometer data to stillness detector. */
- gyro_still_det_update(&gyro_cal->mag_stillness_detect,
- gyro_cal->stillness_win_endtime_us,
- sample_time_us, x, y, z);
-
- /* Received a magnetometer sample; incorporate it into detection. */
- gyro_cal->using_mag_sensor = true;
-
- /*
- * Perform a device stillness check, set next window end-time, and
- * possibly do a gyro bias calibration and stillness detector reset.
- */
- device_stillness_check(gyro_cal, sample_time_us);
-}
-
-void gyro_cal_update_accel(struct gyro_cal *gyro_cal, uint32_t sample_time_us,
- fp_t x, fp_t y, fp_t z)
-{
- /* Pass accelerometer data to stillnesss detector. */
- gyro_still_det_update(&gyro_cal->accel_stillness_detect,
- gyro_cal->stillness_win_endtime_us,
- sample_time_us, x, y, z);
-
- /*
- * Perform a device stillness check, set next window end-time, and
- * possibly do a gyro bias calibration and stillness detector reset.
- */
- device_stillness_check(gyro_cal, sample_time_us);
-}
-
-/**
- * Handle the case where the device is found to be still. This function should
- * be called from device_stillness_check.
- *
- * @param gyro_cal Pointer to the gyroscope calibration struct.
- */
-static void handle_device_is_still(struct gyro_cal *gyro_cal)
-{
- /*
- * Device is "still" logic:
- * If not previously still, then record the start time.
- * If stillness period is too long, then do a calibration.
- * Otherwise, continue collecting stillness data.
- */
- bool stillness_duration_exceeded = false;
-
- /*
- * If device was not previously still, set new start timestamp.
- */
- if (!gyro_cal->prev_still) {
- /*
- * Record the starting timestamp of the current stillness
- * window. This enables the calculation of total duration of
- * the stillness period.
- */
- gyro_cal->start_still_time_us =
- gyro_cal->gyro_stillness_detect.window_start_time;
- }
-
- /*
- * Check to see if current stillness period exceeds the desired limit.
- */
- stillness_duration_exceeded =
- gyro_cal->gyro_stillness_detect.last_sample_time >=
- (gyro_cal->start_still_time_us +
- gyro_cal->max_still_duration_us);
-
- /* Track the new stillness mean and temperature data. */
- gyro_still_mean_tracker_store(gyro_cal);
- gyro_temperature_stats_tracker_store(gyro_cal);
-
- if (stillness_duration_exceeded) {
- /*
- * The current stillness has gone too long. Do a calibration
- * with the current data and reset.
- */
-
- /*
- * Updates the gyro bias estimate with the current window data
- * and resets the stats.
- */
- gyro_still_det_reset(&gyro_cal->accel_stillness_detect,
- /*reset_stats=*/true);
- gyro_still_det_reset(&gyro_cal->gyro_stillness_detect,
- /*reset_stats=*/true);
- gyro_still_det_reset(&gyro_cal->mag_stillness_detect,
- /*reset_stats=*/true);
-
- /*
- * Resets the local calculations because the stillness
- * period is over.
- */
- gyro_still_mean_tracker_reset(gyro_cal);
- gyro_temperature_stats_tracker_reset(gyro_cal);
-
- /* Computes a new gyro offset estimate. */
- compute_gyro_cal(
- gyro_cal,
- gyro_cal->gyro_stillness_detect.last_sample_time);
-
- /*
- * Update stillness flag. Force the start of a new
- * stillness period.
- */
- gyro_cal->prev_still = false;
- } else {
- /* Continue collecting stillness data. */
-
- /* Extend the stillness period. */
- gyro_still_det_reset(&gyro_cal->accel_stillness_detect,
- /*reset_stats=*/false);
- gyro_still_det_reset(&gyro_cal->gyro_stillness_detect,
- /*reset_stats=*/false);
- gyro_still_det_reset(&gyro_cal->mag_stillness_detect,
- /*reset_stats=*/false);
-
- /* Update the stillness flag. */
- gyro_cal->prev_still = true;
- }
-}
-
-static void handle_device_not_still(struct gyro_cal *gyro_cal)
-{
- /* Device is NOT still; motion detected. */
-
- /*
- * If device was previously still and the total stillness
- * duration is not "too short", then do a calibration with the
- * data accumulated thus far.
- */
- bool stillness_duration_too_short =
- gyro_cal->gyro_stillness_detect.window_start_time <
- (gyro_cal->start_still_time_us +
- gyro_cal->min_still_duration_us);
-
- if (gyro_cal->prev_still && !stillness_duration_too_short)
- compute_gyro_cal(
- gyro_cal,
- gyro_cal->gyro_stillness_detect.window_start_time);
-
- /* Reset the stillness detectors and the stats. */
- gyro_still_det_reset(&gyro_cal->accel_stillness_detect,
- /*reset_stats=*/true);
- gyro_still_det_reset(&gyro_cal->gyro_stillness_detect,
- /*reset_stats=*/true);
- gyro_still_det_reset(&gyro_cal->mag_stillness_detect,
- /*reset_stats=*/true);
-
- /* Resets the temperature and sensor mean data. */
- gyro_temperature_stats_tracker_reset(gyro_cal);
- gyro_still_mean_tracker_reset(gyro_cal);
-
- /* Update stillness flag. */
- gyro_cal->prev_still = false;
-}
-
-void device_stillness_check(struct gyro_cal *gyro_cal, uint32_t sample_time_us)
-{
- bool min_max_temp_exceeded = false;
- bool mean_not_stable = false;
- bool device_is_still = false;
- fp_t conf_not_rot = INT_TO_FP(0);
- fp_t conf_not_accel = INT_TO_FP(0);
- fp_t conf_still = INT_TO_FP(0);
-
- /* Check the window timer. */
- check_window(gyro_cal, sample_time_us);
-
- /* Is there enough data to do a stillness calculation? */
- if ((!gyro_cal->mag_stillness_detect.stillness_window_ready &&
- gyro_cal->using_mag_sensor) ||
- !gyro_cal->accel_stillness_detect.stillness_window_ready ||
- !gyro_cal->gyro_stillness_detect.stillness_window_ready)
- return; /* Not yet, wait for more data. */
-
- /* Set the next window end-time for the stillness detectors. */
- gyro_cal->stillness_win_endtime_us =
- sample_time_us + gyro_cal->window_time_duration_us;
-
- /* Update the confidence scores for all sensors. */
- gyro_still_det_compute(&gyro_cal->accel_stillness_detect);
- gyro_still_det_compute(&gyro_cal->gyro_stillness_detect);
- if (gyro_cal->using_mag_sensor) {
- gyro_still_det_compute(&gyro_cal->mag_stillness_detect);
- } else {
- /*
- * Not using magnetometer, force stillness confidence to 100%.
- */
- gyro_cal->mag_stillness_detect.stillness_confidence =
- INT_TO_FP(1);
- }
-
- /* Updates the mean tracker data. */
- gyro_still_mean_tracker_update(gyro_cal);
-
- /*
- * Determine motion confidence scores (rotation, accelerating, and
- * stillness).
- */
- conf_not_rot =
- fp_mul(gyro_cal->gyro_stillness_detect.stillness_confidence,
- gyro_cal->mag_stillness_detect.stillness_confidence);
- conf_not_accel = gyro_cal->accel_stillness_detect.stillness_confidence;
- conf_still = fp_mul(conf_not_rot, conf_not_accel);
-
- /* Evaluate the mean and temperature gate functions. */
- mean_not_stable = gyro_still_mean_tracker_eval(gyro_cal);
- min_max_temp_exceeded = gyro_temperature_stats_tracker_eval(gyro_cal);
-
- /* Determines if the device is currently still. */
- device_is_still = (conf_still > gyro_cal->stillness_threshold) &&
- !mean_not_stable && !min_max_temp_exceeded;
-
- if (device_is_still)
- handle_device_is_still(gyro_cal);
- else
- handle_device_not_still(gyro_cal);
-
- /* Reset the window timer after we have processed data. */
- gyro_cal->gyro_window_start_us = sample_time_us;
-}
-
-void compute_gyro_cal(struct gyro_cal *gyro_cal, uint32_t calibration_time_us)
-{
- /* Check to see if new calibration values is within acceptable range. */
- if (!(gyro_cal->gyro_stillness_detect.prev_mean[X] < MAX_GYRO_BIAS &&
- gyro_cal->gyro_stillness_detect.prev_mean[X] > -MAX_GYRO_BIAS &&
- gyro_cal->gyro_stillness_detect.prev_mean[Y] < MAX_GYRO_BIAS &&
- gyro_cal->gyro_stillness_detect.prev_mean[Y] > -MAX_GYRO_BIAS &&
- gyro_cal->gyro_stillness_detect.prev_mean[Z] < MAX_GYRO_BIAS &&
- gyro_cal->gyro_stillness_detect.prev_mean[Z] > -MAX_GYRO_BIAS))
- /* Outside of range. Ignore, reset, and continue. */
- return;
-
- /* Record the new gyro bias offset calibration. */
- gyro_cal->bias_x = gyro_cal->gyro_stillness_detect.prev_mean[X];
- gyro_cal->bias_y = gyro_cal->gyro_stillness_detect.prev_mean[Y];
- gyro_cal->bias_z = gyro_cal->gyro_stillness_detect.prev_mean[Z];
-
- /*
- * Store the calibration temperature (using the mean temperature over
- * the "stillness" period).
- */
- gyro_cal->bias_temperature_kelvin = gyro_cal->temperature_mean_kelvin;
-
- /* Store the calibration time stamp. */
- gyro_cal->calibration_time_us = calibration_time_us;
-
- /* Record the final stillness confidence. */
- gyro_cal->stillness_confidence = fp_mul(
- gyro_cal->gyro_stillness_detect.prev_stillness_confidence,
- gyro_cal->accel_stillness_detect.prev_stillness_confidence);
- gyro_cal->stillness_confidence = fp_mul(
- gyro_cal->stillness_confidence,
- gyro_cal->mag_stillness_detect.prev_stillness_confidence);
-
- /* Set flag to indicate a new gyro calibration value is available. */
- gyro_cal->new_gyro_cal_available = true;
-}
-
-void check_window(struct gyro_cal *gyro_cal, uint32_t sample_time_us)
-{
- bool window_timeout;
-
- /* Check for initialization of the window time (=0). */
- if (gyro_cal->gyro_window_start_us <= 0)
- return;
-
- /*
- * Checks for the following window timeout conditions:
- * i. The current timestamp has exceeded the allowed window duration.
- * ii. A timestamp was received that has jumped backwards by more than
- * the allowed window duration (e.g., timestamp clock roll-over).
- */
- window_timeout =
- (sample_time_us > gyro_cal->gyro_window_timeout_duration_us +
- gyro_cal->gyro_window_start_us) ||
- (sample_time_us + gyro_cal->gyro_window_timeout_duration_us <
- gyro_cal->gyro_window_start_us);
-
- /* If a timeout occurred then reset to known good state. */
- if (window_timeout) {
- /* Reset stillness detectors and restart data capture. */
- gyro_still_det_reset(&gyro_cal->accel_stillness_detect,
- /*reset_stats=*/true);
- gyro_still_det_reset(&gyro_cal->gyro_stillness_detect,
- /*reset_stats=*/true);
- gyro_still_det_reset(&gyro_cal->mag_stillness_detect,
- /*reset_stats=*/true);
-
- /* Resets the temperature and sensor mean data. */
- gyro_temperature_stats_tracker_reset(gyro_cal);
- gyro_still_mean_tracker_reset(gyro_cal);
-
- /* Resets the stillness window end-time. */
- gyro_cal->stillness_win_endtime_us = 0;
-
- /* Force stillness confidence to zero. */
- gyro_cal->accel_stillness_detect.prev_stillness_confidence = 0;
- gyro_cal->gyro_stillness_detect.prev_stillness_confidence = 0;
- gyro_cal->mag_stillness_detect.prev_stillness_confidence = 0;
- gyro_cal->stillness_confidence = 0;
- gyro_cal->prev_still = false;
-
- /*
- * If there are no magnetometer samples being received then
- * operate the calibration algorithm without this sensor.
- */
- if (!gyro_cal->mag_stillness_detect.stillness_window_ready &&
- gyro_cal->using_mag_sensor) {
- gyro_cal->using_mag_sensor = false;
- }
-
- /* Assert window timeout flags. */
- gyro_cal->gyro_window_start_us = 0;
- }
-}
-
-void gyro_temperature_stats_tracker_reset(struct gyro_cal *gyro_cal)
-{
- /* Resets the mean accumulator. */
- gyro_cal->temperature_mean_tracker.num_points = 0;
- gyro_cal->temperature_mean_tracker.mean_accumulator = INT_TO_FP(0);
-
- /* Initializes the min/max temperatures values. */
- gyro_cal->temperature_mean_tracker.temperature_min_kelvin = 0x7fff;
- gyro_cal->temperature_mean_tracker.temperature_max_kelvin = 0xffff;
-}
-
-void gyro_temperature_stats_tracker_update(struct gyro_cal *gyro_cal,
- int temperature_kelvin)
-{
- /* Does the mean accumulation. */
- gyro_cal->temperature_mean_tracker.mean_accumulator +=
- temperature_kelvin;
- gyro_cal->temperature_mean_tracker.num_points++;
-
- /* Tracks the min, max, and latest temperature values. */
- gyro_cal->temperature_mean_tracker.latest_temperature_kelvin =
- temperature_kelvin;
- if (gyro_cal->temperature_mean_tracker.temperature_min_kelvin >
- temperature_kelvin) {
- gyro_cal->temperature_mean_tracker.temperature_min_kelvin =
- temperature_kelvin;
- }
- if (gyro_cal->temperature_mean_tracker.temperature_max_kelvin <
- temperature_kelvin) {
- gyro_cal->temperature_mean_tracker.temperature_max_kelvin =
- temperature_kelvin;
- }
-}
-
-void gyro_temperature_stats_tracker_store(struct gyro_cal *gyro_cal)
-{
- /*
- * Store the most recent temperature statistics data to the
- * gyro_cal data structure. This functionality allows previous
- * results to be recalled when the device suddenly becomes "not
- * still".
- */
- if (gyro_cal->temperature_mean_tracker.num_points > 0)
- gyro_cal->temperature_mean_kelvin =
- gyro_cal->temperature_mean_tracker.mean_accumulator /
- gyro_cal->temperature_mean_tracker.num_points;
- else
- gyro_cal->temperature_mean_kelvin =
- gyro_cal->temperature_mean_tracker
- .latest_temperature_kelvin;
-}
-
-bool gyro_temperature_stats_tracker_eval(struct gyro_cal *gyro_cal)
-{
- bool min_max_temp_exceeded = false;
-
- /* Determines if the min/max delta exceeded the set limit. */
- if (gyro_cal->temperature_mean_tracker.num_points > 0) {
- min_max_temp_exceeded =
- (gyro_cal->temperature_mean_tracker
- .temperature_max_kelvin -
- gyro_cal->temperature_mean_tracker
- .temperature_min_kelvin) >
- gyro_cal->temperature_delta_limit_kelvin;
- }
-
- return min_max_temp_exceeded;
-}
-
-void gyro_still_mean_tracker_reset(struct gyro_cal *gyro_cal)
-{
- size_t i;
-
- /* Resets the min/max window mean values to a default value. */
- for (i = 0; i < 3; i++) {
- gyro_cal->window_mean_tracker.gyro_winmean_min[i] = FLT_MAX;
- gyro_cal->window_mean_tracker.gyro_winmean_max[i] = -FLT_MAX;
- }
-}
-
-void gyro_still_mean_tracker_update(struct gyro_cal *gyro_cal)
-{
- int i;
-
- /* Computes the min/max window mean values. */
- for (i = 0; i < 3; ++i) {
- if (gyro_cal->window_mean_tracker.gyro_winmean_min[i] >
- gyro_cal->gyro_stillness_detect.win_mean[i]) {
- gyro_cal->window_mean_tracker.gyro_winmean_min[i] =
- gyro_cal->gyro_stillness_detect.win_mean[i];
- }
- if (gyro_cal->window_mean_tracker.gyro_winmean_max[i] <
- gyro_cal->gyro_stillness_detect.win_mean[i]) {
- gyro_cal->window_mean_tracker.gyro_winmean_max[i] =
- gyro_cal->gyro_stillness_detect.win_mean[i];
- }
- }
-}
-
-void gyro_still_mean_tracker_store(struct gyro_cal *gyro_cal)
-{
- /*
- * Store the most recent "stillness" mean data to the gyro_cal
- * data structure. This functionality allows previous results to
- * be recalled when the device suddenly becomes "not still".
- */
- memcpy(gyro_cal->gyro_winmean_min,
- gyro_cal->window_mean_tracker.gyro_winmean_min,
- sizeof(gyro_cal->window_mean_tracker.gyro_winmean_min));
- memcpy(gyro_cal->gyro_winmean_max,
- gyro_cal->window_mean_tracker.gyro_winmean_max,
- sizeof(gyro_cal->window_mean_tracker.gyro_winmean_max));
-}
-
-bool gyro_still_mean_tracker_eval(struct gyro_cal *gyro_cal)
-{
- bool mean_not_stable = false;
- size_t i;
-
- /*
- * Performs the stability check and returns the 'true' if the
- * difference between min/max window mean value is outside the
- * stable range.
- */
- for (i = 0; i < 3 && !mean_not_stable; i++) {
- mean_not_stable |=
- (gyro_cal->window_mean_tracker.gyro_winmean_max[i] -
- gyro_cal->window_mean_tracker.gyro_winmean_min[i]) >
- gyro_cal->stillness_mean_delta_limit;
- }
-
- return mean_not_stable;
-}
diff --git a/common/gyro_still_det.c b/common/gyro_still_det.c
deleted file mode 100644
index 4574e22e5f..0000000000
--- a/common/gyro_still_det.c
+++ /dev/null
@@ -1,242 +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.
- */
-
-#include "gyro_still_det.h"
-#include "vec3.h"
-
-/* Enforces the limits of an input value [0,1]. */
-static fp_t gyro_still_det_limit(fp_t value);
-
-void gyro_still_det_update(struct gyro_still_det *gyro_still_det,
- uint32_t stillness_win_endtime, uint32_t sample_time,
- fp_t x, fp_t y, fp_t z)
-{
- fp_t delta = INT_TO_FP(0);
-
- /*
- * Using the method of the assumed mean to preserve some numerical
- * stability while avoiding per-sample divisions that the more
- * numerically stable Welford method would afford.
- *
- * Reference for the numerical method used below to compute the
- * online mean and variance statistics:
- * 1). en.wikipedia.org/wiki/assumed_mean
- */
-
- /* Increment the number of samples. */
- gyro_still_det->num_acc_samples++;
-
- /* Online computation of mean for the running stillness period. */
- gyro_still_det->mean[X] += x;
- gyro_still_det->mean[Y] += y;
- gyro_still_det->mean[Z] += z;
-
- /* Is this the first sample of a new window? */
- if (gyro_still_det->start_new_window) {
- /* Record the window start time. */
- gyro_still_det->window_start_time = sample_time;
- gyro_still_det->start_new_window = false;
-
- /* Update assumed mean values. */
- gyro_still_det->assumed_mean[X] = x;
- gyro_still_det->assumed_mean[Y] = y;
- gyro_still_det->assumed_mean[Z] = z;
-
- /* Reset current window mean and variance. */
- gyro_still_det->num_acc_win_samples = 0;
- gyro_still_det->win_mean[X] = INT_TO_FP(0);
- gyro_still_det->win_mean[Y] = INT_TO_FP(0);
- gyro_still_det->win_mean[Z] = INT_TO_FP(0);
- gyro_still_det->acc_var[X] = INT_TO_FP(0);
- gyro_still_det->acc_var[Y] = INT_TO_FP(0);
- gyro_still_det->acc_var[Z] = INT_TO_FP(0);
- } else {
- /*
- * Check to see if we have enough samples to compute a stillness
- * confidence score.
- */
- gyro_still_det->stillness_window_ready =
- (sample_time >= stillness_win_endtime) &&
- (gyro_still_det->num_acc_samples > 1);
- }
-
- /* Record the most recent sample time stamp. */
- gyro_still_det->last_sample_time = sample_time;
-
- /* Online window mean and variance ("one-pass" accumulation). */
- gyro_still_det->num_acc_win_samples++;
-
- delta = (x - gyro_still_det->assumed_mean[X]);
- gyro_still_det->win_mean[X] += delta;
- gyro_still_det->acc_var[X] += fp_sq(delta);
-
- delta = (y - gyro_still_det->assumed_mean[Y]);
- gyro_still_det->win_mean[Y] += delta;
- gyro_still_det->acc_var[Y] += fp_sq(delta);
-
- delta = (z - gyro_still_det->assumed_mean[Z]);
- gyro_still_det->win_mean[Z] += delta;
- gyro_still_det->acc_var[Z] += fp_sq(delta);
-}
-
-fp_t gyro_still_det_compute(struct gyro_still_det *gyro_still_det)
-{
- fp_t tmp_denom = INT_TO_FP(1);
- fp_t tmp_denom_mean = INT_TO_FP(1);
- fp_t tmp;
- fp_t upper_var_thresh, lower_var_thresh;
-
- /* Don't divide by zero (not likely, but a precaution). */
- if (gyro_still_det->num_acc_win_samples > 1) {
- tmp_denom = fp_div(
- tmp_denom,
- INT_TO_FP(gyro_still_det->num_acc_win_samples - 1));
- tmp_denom_mean =
- fp_div(tmp_denom_mean,
- INT_TO_FP(gyro_still_det->num_acc_win_samples));
- } else {
- /* Return zero stillness confidence. */
- gyro_still_det->stillness_confidence = 0;
- return gyro_still_det->stillness_confidence;
- }
-
- /* Update the final calculation of window mean and variance. */
- tmp = gyro_still_det->win_mean[X];
- gyro_still_det->win_mean[X] =
- fp_mul(gyro_still_det->win_mean[X], tmp_denom_mean);
- gyro_still_det->win_var[X] =
- fp_mul((gyro_still_det->acc_var[X] -
- fp_mul(gyro_still_det->win_mean[X], tmp)),
- tmp_denom);
-
- tmp = gyro_still_det->win_mean[Y];
- gyro_still_det->win_mean[Y] =
- fp_mul(gyro_still_det->win_mean[Y], tmp_denom_mean);
- gyro_still_det->win_var[Y] =
- fp_mul((gyro_still_det->acc_var[Y] -
- fp_mul(gyro_still_det->win_mean[Y], tmp)),
- tmp_denom);
-
- tmp = gyro_still_det->win_mean[Z];
- gyro_still_det->win_mean[Z] =
- fp_mul(gyro_still_det->win_mean[Z], tmp_denom_mean);
- gyro_still_det->win_var[Z] =
- fp_mul((gyro_still_det->acc_var[Z] -
- fp_mul(gyro_still_det->win_mean[Z], tmp)),
- tmp_denom);
-
- /* Adds the assumed mean value back to the total mean calculation. */
- gyro_still_det->win_mean[X] += gyro_still_det->assumed_mean[X];
- gyro_still_det->win_mean[Y] += gyro_still_det->assumed_mean[Y];
- gyro_still_det->win_mean[Z] += gyro_still_det->assumed_mean[Z];
-
- /* Define the variance thresholds. */
- upper_var_thresh = gyro_still_det->var_threshold +
- gyro_still_det->confidence_delta;
-
- lower_var_thresh = gyro_still_det->var_threshold -
- gyro_still_det->confidence_delta;
-
- /* Compute the stillness confidence score. */
- if ((gyro_still_det->win_var[X] > upper_var_thresh) ||
- (gyro_still_det->win_var[Y] > upper_var_thresh) ||
- (gyro_still_det->win_var[Z] > upper_var_thresh)) {
- /*
- * Sensor variance exceeds the upper threshold (i.e., motion
- * detected). Set stillness confidence equal to 0.
- */
- gyro_still_det->stillness_confidence = 0;
- } else if ((gyro_still_det->win_var[X] <= lower_var_thresh) &&
- (gyro_still_det->win_var[Y] <= lower_var_thresh) &&
- (gyro_still_det->win_var[Z] <= lower_var_thresh)) {
- /*
- * Sensor variance is below the lower threshold (i.e.
- * stillness detected).
- * Set stillness confidence equal to 1.
- */
- gyro_still_det->stillness_confidence = INT_TO_FP(1);
- } else {
- /*
- * Motion detection thresholds not exceeded. Compute the
- * stillness confidence score.
- */
- fp_t var_thresh = gyro_still_det->var_threshold;
- fpv3_t limit;
-
- /*
- * Compute the stillness confidence score.
- * Each axis score is limited [0,1].
- */
- tmp_denom = fp_div(INT_TO_FP(1),
- (upper_var_thresh - lower_var_thresh));
- limit[X] = gyro_still_det_limit(
- FLOAT_TO_FP(0.5f) -
- fp_mul(gyro_still_det->win_var[X] - var_thresh,
- tmp_denom));
- limit[Y] = gyro_still_det_limit(
- FLOAT_TO_FP(0.5f) -
- fp_mul(gyro_still_det->win_var[Y] - var_thresh,
- tmp_denom));
- limit[Z] = gyro_still_det_limit(
- FLOAT_TO_FP(0.5f) -
- fp_mul(gyro_still_det->win_var[Z] - var_thresh,
- tmp_denom));
-
- gyro_still_det->stillness_confidence =
- fp_mul(limit[X], fp_mul(limit[Y], limit[Z]));
- }
-
- /* Return the stillness confidence. */
- return gyro_still_det->stillness_confidence;
-}
-
-void gyro_still_det_reset(struct gyro_still_det *gyro_still_det,
- bool reset_stats)
-{
- fp_t tmp_denom = INT_TO_FP(1);
-
- /* Reset the stillness data ready flag. */
- gyro_still_det->stillness_window_ready = false;
-
- /* Signal to start capture of next stillness data window. */
- gyro_still_det->start_new_window = true;
-
- /* Track the stillness confidence (current->previous). */
- gyro_still_det->prev_stillness_confidence =
- gyro_still_det->stillness_confidence;
-
- /* Track changes in the mean estimate. */
- if (gyro_still_det->num_acc_samples > INT_TO_FP(1))
- tmp_denom =
- fp_div(INT_TO_FP(1), gyro_still_det->num_acc_samples);
-
- gyro_still_det->prev_mean[X] =
- fp_mul(gyro_still_det->mean[X], tmp_denom);
- gyro_still_det->prev_mean[Y] =
- fp_mul(gyro_still_det->mean[Y], tmp_denom);
- gyro_still_det->prev_mean[Z] =
- fp_mul(gyro_still_det->mean[Z], tmp_denom);
-
- /* Reset the current statistics to zero. */
- if (reset_stats) {
- gyro_still_det->num_acc_samples = 0;
- gyro_still_det->mean[X] = INT_TO_FP(0);
- gyro_still_det->mean[Y] = INT_TO_FP(0);
- gyro_still_det->mean[Z] = INT_TO_FP(0);
- gyro_still_det->acc_var[X] = INT_TO_FP(0);
- gyro_still_det->acc_var[Y] = INT_TO_FP(0);
- gyro_still_det->acc_var[Z] = INT_TO_FP(0);
- }
-}
-
-fp_t gyro_still_det_limit(fp_t value)
-{
- if (value < INT_TO_FP(0))
- value = INT_TO_FP(0);
- else if (value > INT_TO_FP(1))
- value = INT_TO_FP(1);
-
- return value;
-}
diff --git a/common/host_command_controller.c b/common/host_command_controller.c
deleted file mode 100644
index 0d221e44e3..0000000000
--- a/common/host_command_controller.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/* Copyright 2014 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.
- */
-
-/* Host command controller module for Chrome EC */
-
-#include "common.h"
-#include "console.h"
-#include "host_command.h"
-#include "i2c.h"
-#include "task.h"
-#include "timer.h"
-#include "usb_pd.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_HOSTCMD, outstr)
-#define CPRINTS(format, args...) cprints(CC_HOSTCMD, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_HOSTCMD, format, ## args)
-
-/* Number of attempts for each PD host command */
-#define PD_HOST_COMMAND_ATTEMPTS 3
-
-static struct mutex pd_mutex;
-
-/**
- * Non-task-safe internal version of pd_host_command().
- *
- * Do not call this version directly! Use pd_host_command().
- */
-static int pd_host_command_internal(int command, int version,
- const void *outdata, int outsize,
- void *indata, int insize)
-{
- int ret, i;
- int resp_len;
- struct ec_host_request rq;
- struct ec_host_response rs;
- static uint8_t req_buf[EC_LPC_HOST_PACKET_SIZE];
- static uint8_t resp_buf[EC_LPC_HOST_PACKET_SIZE];
- uint8_t sum = 0;
- const uint8_t *c;
- uint8_t *d;
-
- /* Fail if output size is too big */
- if (outsize + sizeof(rq) > EC_LPC_HOST_PACKET_SIZE)
- return -EC_RES_REQUEST_TRUNCATED;
-
- /* Fill in request packet */
- rq.struct_version = EC_HOST_REQUEST_VERSION;
- rq.checksum = 0;
- rq.command = command;
- rq.command_version = version;
- rq.reserved = 0;
- rq.data_len = outsize;
-
- /* Copy data and start checksum */
- for (i = 0, c = (const uint8_t *)outdata; i < outsize; i++, c++) {
- req_buf[sizeof(rq) + 1 + i] = *c;
- sum += *c;
- }
-
- /* Finish checksum */
- for (i = 0, c = (const uint8_t *)&rq; i < sizeof(rq); i++, c++)
- sum += *c;
-
- /* Write checksum field so the entire packet sums to 0 */
- rq.checksum = (uint8_t)(-sum);
-
- /* Copy header */
- for (i = 0, c = (const uint8_t *)&rq; i < sizeof(rq); i++, c++)
- req_buf[1 + i] = *c;
-
- /* Set command to use protocol v3 */
- req_buf[0] = EC_COMMAND_PROTOCOL_3;
-
- /*
- * Transmit all data and receive 2 bytes for return value and response
- * length.
- */
- i2c_lock(I2C_PORT_PD_MCU, 1);
- i2c_set_timeout(I2C_PORT_PD_MCU, PD_HOST_COMMAND_TIMEOUT_US);
- ret = i2c_xfer_unlocked(I2C_PORT_PD_MCU,
- CONFIG_USB_PD_I2C_ADDR_FLAGS,
- &req_buf[0], outsize + sizeof(rq) + 1,
- &resp_buf[0], 2, I2C_XFER_START);
- i2c_set_timeout(I2C_PORT_PD_MCU, 0);
- if (ret) {
- i2c_lock(I2C_PORT_PD_MCU, 0);
- CPRINTS("i2c transaction 1 failed: %d", ret);
- return -EC_RES_BUS_ERROR;
- }
-
- resp_len = resp_buf[1];
-
- if (resp_len > (insize + sizeof(rs))) {
- /* Do a read to generate stop condition */
- i2c_xfer_unlocked(I2C_PORT_PD_MCU,
- CONFIG_USB_PD_I2C_ADDR_FLAGS,
- 0, 0, &resp_buf[2], 1, I2C_XFER_STOP);
- i2c_lock(I2C_PORT_PD_MCU, 0);
- CPRINTS("response size is too large %d > %d",
- resp_len, insize + sizeof(rs));
- return -EC_RES_RESPONSE_TOO_BIG;
- }
-
- /* Receive remaining data */
- ret = i2c_xfer_unlocked(I2C_PORT_PD_MCU,
- CONFIG_USB_PD_I2C_ADDR_FLAGS,
- 0, 0,
- &resp_buf[2], resp_len, I2C_XFER_STOP);
- i2c_lock(I2C_PORT_PD_MCU, 0);
- if (ret) {
- CPRINTS("i2c transaction 2 failed: %d", ret);
- return -EC_RES_BUS_ERROR;
- }
-
- /* Check for host command error code */
- ret = resp_buf[0];
- if (ret) {
- CPRINTS("command 0x%02x returned error %d", command, ret);
- return -ret;
- }
-
- /* Read back response header and start checksum */
- sum = 0;
- for (i = 0, d = (uint8_t *)&rs; i < sizeof(rs); i++, d++) {
- *d = resp_buf[i + 2];
- sum += *d;
- }
-
- if (rs.struct_version != EC_HOST_RESPONSE_VERSION) {
- CPRINTS("PD response version mismatch");
- return -EC_RES_INVALID_RESPONSE;
- }
-
- if (rs.reserved) {
- CPRINTS("PD response reserved != 0");
- return -EC_RES_INVALID_RESPONSE;
- }
-
- if (rs.data_len > insize) {
- CPRINTS("PD returned too much data");
- return -EC_RES_RESPONSE_TOO_BIG;
- }
-
- /* Read back data and update checksum */
- resp_len -= sizeof(rs);
- for (i = 0, d = (uint8_t *)indata; i < resp_len; i++, d++) {
- *d = resp_buf[sizeof(rs) + i + 2];
- sum += *d;
- }
-
-
- if ((uint8_t)sum) {
- CPRINTS("command 0x%02x bad checksum returned: %d",
- command, sum);
- return -EC_RES_INVALID_CHECKSUM;
- }
-
- /* Return output buffer size */
- return resp_len;
-}
-
-int pd_host_command(int command, int version,
- const void *outdata, int outsize,
- void *indata, int insize)
-{
- int rv;
- int tries = 0;
-
- /* Try multiple times to send host command. */
- for (tries = 0; tries < PD_HOST_COMMAND_ATTEMPTS; tries++) {
- /* Acquire mutex */
- mutex_lock(&pd_mutex);
- /* Call internal version of host command */
- rv = pd_host_command_internal(command, version, outdata,
- outsize, indata, insize);
- /* Release mutex */
- mutex_unlock(&pd_mutex);
-
- /* If host command error due to i2c bus error, try again. */
- if (rv != -EC_RES_BUS_ERROR)
- break;
- task_wait_event(50*MSEC);
- }
-
- return rv;
-}
-
-static int command_pd_mcu(int argc, char **argv)
-{
- char *e;
- static char __bss_slow outbuf[128];
- static char __bss_slow inbuf[128];
- int command, version;
- int i, ret, tmp;
-
- if (argc < 3)
- return EC_ERROR_PARAM_COUNT;
-
- command = strtoi(argv[1], &e, 0);
- if (*e)
- return EC_ERROR_PARAM1;
-
- version = strtoi(argv[2], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2;
-
- for (i = 3; i < argc; i++) {
- tmp = strtoi(argv[i], &e, 0);
- if (*e)
- return EC_ERROR_PARAM3;
- outbuf[i-3] = tmp;
- }
-
- ret = pd_host_command(command, version, &outbuf, argc - 3, &inbuf,
- sizeof(inbuf));
-
- ccprintf("Host command 0x%02x, returned %d\n", command, ret);
- for (i = 0; i < ret; i++)
- ccprintf("0x%02x\n", inbuf[i]);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(pdcmd, command_pd_mcu,
- "cmd ver [params]",
- "Send PD host command");
-
diff --git a/common/host_command_pd.c b/common/host_command_pd.c
deleted file mode 100644
index f9b67c8b8d..0000000000
--- a/common/host_command_pd.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/* Copyright 2014 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.
- */
-
-/* Host command module for PD MCU */
-
-#include "charge_state.h"
-#include "common.h"
-#include "console.h"
-#include "gpio.h"
-#include "host_command.h"
-#include "lightbar.h"
-#include "panic.h"
-#include "system.h"
-#include "task.h"
-#include "tcpm/tcpm.h"
-#include "timer.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_PD_HOST_CMD, format, ## args)
-
-#define TASK_EVENT_EXCHANGE_PD_STATUS TASK_EVENT_CUSTOM_BIT(0)
-#define TASK_EVENT_HIBERNATING TASK_EVENT_CUSTOM_BIT(1)
-
-/* Define local option for if we are a TCPM with an off chip TCPC */
-#if defined(CONFIG_USB_POWER_DELIVERY) && !defined(CONFIG_USB_PD_TCPM_STUB)
-#define USB_TCPM_WITH_OFF_CHIP_TCPC
-#endif
-
-#ifdef CONFIG_HOSTCMD_PD_CHG_CTRL
-/* By default allow 5V charging only for the dead battery case */
-static enum pd_charge_state charge_state = PD_CHARGE_5V;
-
-#define CHARGE_PORT_UNINITIALIZED -2
-static int charge_port = CHARGE_PORT_UNINITIALIZED;
-
-int pd_get_active_charge_port(void)
-{
- return charge_port;
-}
-#endif /* CONFIG_HOSTCMD_PD_CHG_CTRL */
-
-void host_command_pd_send_status(enum pd_charge_state new_chg_state)
-{
-#ifdef CONFIG_HOSTCMD_PD_CHG_CTRL
- /* Update PD MCU charge state if necessary */
- if (new_chg_state != PD_CHARGE_NO_CHANGE)
- charge_state = new_chg_state;
-#endif
- /* Wake PD HC task to send status */
- task_set_event(TASK_ID_PDCMD, TASK_EVENT_EXCHANGE_PD_STATUS);
-}
-
-void host_command_pd_request_hibernate(void)
-{
- task_set_event(TASK_ID_PDCMD, TASK_EVENT_HIBERNATING);
-}
-
-#ifdef CONFIG_HOSTCMD_PD
-static int pd_send_host_command(struct ec_params_pd_status *ec_status,
- struct ec_response_pd_status *pd_status)
-{
- return pd_host_command(EC_CMD_PD_EXCHANGE_STATUS,
- EC_VER_PD_EXCHANGE_STATUS, ec_status,
- sizeof(struct ec_params_pd_status), pd_status,
- sizeof(struct ec_response_pd_status));
-}
-
-static void pd_exchange_update_ec_status(struct ec_params_pd_status *ec_status,
- uint32_t ec_state)
-{
- /* Send PD charge state and battery state of charge */
-#ifdef CONFIG_HOSTCMD_PD_CHG_CTRL
- ec_status->charge_state = charge_state;
-#endif
- if (charge_get_flags() & CHARGE_FLAG_BATT_RESPONSIVE)
- ec_status->batt_soc = charge_get_percent();
- else
- ec_status->batt_soc = -1;
- ec_status->status = ec_state;
-}
-
-#ifdef CONFIG_HOSTCMD_PD_PANIC
-static void pd_check_panic(struct ec_response_pd_status *pd_status)
-{
- static int pd_in_rw;
-
- /*
- * Check if PD MCU is in RW. If PD MCU was in RW, is now in RO,
- * AND it did not sysjump to RO, then it must have crashed, and
- * therefore we should panic as well.
- */
- if (pd_status->status & PD_STATUS_IN_RW) {
- pd_in_rw = 1;
- } else if (pd_in_rw &&
- !(pd_status->status & PD_STATUS_JUMPED_TO_IMAGE)) {
- panic_printf("PD crash");
- software_panic(PANIC_SW_PD_CRASH, 0);
- }
-}
-#endif /* CONFIG_HOSTCMD_PD_PANIC */
-
-#ifdef CONFIG_HOSTCMD_PD_CHG_CTRL
-static void pd_check_chg_status(struct ec_response_pd_status *pd_status)
-{
- int rv;
-#ifdef HAS_TASK_LIGHTBAR
- /*
- * If charge port has changed, and it was initialized, then show
- * battery status on lightbar.
- */
- if (pd_status->active_charge_port != charge_port) {
- if (charge_port != CHARGE_PORT_UNINITIALIZED) {
- charge_port = pd_status->active_charge_port;
- lightbar_sequence(LIGHTBAR_TAP);
- } else {
- charge_port = pd_status->active_charge_port;
- }
- }
-#else
- /* Store the active charge port */
- charge_port = pd_status->active_charge_port;
-#endif
-
- /* Set input current limit */
- rv = charge_set_input_current_limit(MAX(pd_status->curr_lim_ma,
- CONFIG_CHARGER_INPUT_CURRENT), 0);
- if (rv < 0)
- CPRINTS("Failed to set input curr limit from PD MCU");
-}
-#endif /* CONFIG_HOSTCMD_PD_CHG_CTRL */
-#endif /* CONFIG_HOSTCMD_PD */
-
-#ifdef USB_TCPM_WITH_OFF_CHIP_TCPC
-static void pd_service_tcpc_ports(uint16_t port_status)
-{
- int i;
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- if ((port_status & (PD_STATUS_TCPC_ALERT_0 << i)) &&
- pd_is_port_enabled(i))
- tcpc_alert(i);
- }
-}
-
-static int pd_get_alert(void)
-{
-#ifdef CONFIG_HOSTCMD_PD
- return !gpio_get_level(GPIO_PD_MCU_INT);
-#else
- return !!tcpc_get_alert_status();
-#endif
-}
-
-#endif /* USB_TCPM_WITH_OFF_CHIP_TCPC */
-
-static void pd_exchange_status(uint32_t ec_state)
-{
-#ifdef USB_TCPM_WITH_OFF_CHIP_TCPC
- int first_exchange = 1;
-#endif
-
-#ifdef CONFIG_HOSTCMD_PD
- struct ec_params_pd_status ec_status;
- struct ec_response_pd_status pd_status;
- int rv;
-
- pd_exchange_update_ec_status(&ec_status, ec_state);
-#endif
-
-#ifdef USB_TCPM_WITH_OFF_CHIP_TCPC
- /* Loop until the alert gpio is not active */
- do {
-#endif
-
-#ifdef CONFIG_HOSTCMD_PD
- rv = pd_send_host_command(&ec_status, &pd_status);
- if (rv < 0) {
- CPRINTS("Host command to PD MCU failed: %d", rv);
- return;
- }
-
-#ifdef CONFIG_HOSTCMD_PD_PANIC
- pd_check_panic(&pd_status);
-#endif
-
-#ifdef CONFIG_HOSTCMD_PD_CHG_CTRL
- pd_check_chg_status(&pd_status);
-#endif
-#endif /* CONFIG_HOSTCMD_PD */
-
-#ifdef USB_TCPM_WITH_OFF_CHIP_TCPC
-#ifdef CONFIG_HOSTCMD_PD
- pd_service_tcpc_ports(pd_status.status);
-#else
- pd_service_tcpc_ports(tcpc_get_alert_status());
-#endif
-
- if (!first_exchange)
- /* Delay to prevent task starvation */
- usleep(5*MSEC);
- first_exchange = 0;
- } while (pd_get_alert());
-#endif /* USB_TCPM_WITH_OFF_CHIP_TCPC */
-}
-
-void pd_command_task(void *u)
-{
- /* On startup exchange status with the PD */
- pd_exchange_status(0);
-
- while (1) {
- /* Wait for the next command event */
- int evt = task_wait_event(-1);
- uint32_t ec_state = 0;
-
- if (evt & TASK_EVENT_HIBERNATING)
- ec_state = EC_STATUS_HIBERNATING;
-
- /* Process event to send status to PD */
- if ((evt & TASK_EVENT_EXCHANGE_PD_STATUS) ||
- (evt & TASK_EVENT_HIBERNATING))
- pd_exchange_status(ec_state);
- }
-}
-
diff --git a/common/hotword_dsp_api.c b/common/hotword_dsp_api.c
deleted file mode 100644
index dc53cd0055..0000000000
--- a/common/hotword_dsp_api.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2019 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.
- */
-
-#include "audio_codec.h"
-#include "hotword_dsp_api.h"
-
-const int kGoogleHotwordRequiredDataAlignment = 4;
-
-int GoogleHotwordDspInit(void *hotword_memmap)
-{
- return 1;
-}
-
-int GoogleHotwordDspProcess(const void *samples, int num_samples,
- int *preamble_length_ms)
-{
- return 0;
-}
-
-void GoogleHotwordDspReset(void)
-{
-}
-
-int GoogleHotwordDspGetMaximumAudioPreambleMs(void)
-{
- return 0;
-}
-
-int GoogleHotwordVersion(void)
-{
- return 0;
-}
diff --git a/common/i2c_bitbang.c b/common/i2c_bitbang.c
deleted file mode 100644
index 86d76a8b47..0000000000
--- a/common/i2c_bitbang.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/* Copyright 2019 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.
- */
-
-#include "console.h"
-#include "gpio.h"
-#include "i2c_bitbang.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-
-#define CPUTS(str) cputs(CC_I2C, str)
-
-static int started;
-
-/* TODO: respect i2c_port->kbps setting */
-static void i2c_delay(void)
-{
- udelay(5);
-}
-
-/* Number of attempts to unwedge each pin. */
-#define UNWEDGE_SCL_ATTEMPTS 10
-#define UNWEDGE_SDA_ATTEMPTS 3
-
-static void i2c_bitbang_unwedge(const struct i2c_port_t *i2c_port)
-{
- int i, j;
-
- gpio_set_level(i2c_port->scl, 1);
- /*
- * If clock is low, wait for a while in case of clock stretched
- * by a peripheral.
- */
- if (!gpio_get_level(i2c_port->scl)) {
- for (i = 0;; i++) {
- if (i >= UNWEDGE_SCL_ATTEMPTS) {
- /*
- * If we get here, a peripheral is holding the
- * clock low and there is nothing we can do.
- */
- CPUTS("I2C unwedge failed, SCL is held low\n");
- return;
- }
- i2c_delay();
- if (gpio_get_level(i2c_port->scl))
- break;
- }
- }
-
- if (gpio_get_level(i2c_port->sda))
- return;
-
- CPUTS("I2C unwedge called with SDA held low\n");
-
- /* Keep trying to unwedge the SDA line until we run out of attempts. */
- for (i = 0; i < UNWEDGE_SDA_ATTEMPTS; i++) {
- /* Drive the clock high. */
- gpio_set_level(i2c_port->scl, 0);
- i2c_delay();
-
- /*
- * Clock through the problem by clocking out 9 bits. If
- * peripheral releases the SDA line, then we can stop clocking
- * bits and send a STOP.
- */
- for (j = 0; j < 9; j++) {
- if (gpio_get_level(i2c_port->sda))
- break;
-
- gpio_set_level(i2c_port->scl, 0);
- i2c_delay();
- gpio_set_level(i2c_port->scl, 1);
- i2c_delay();
- }
-
- /* Take control of SDA line and issue a STOP command. */
- gpio_set_level(i2c_port->sda, 0);
- i2c_delay();
- gpio_set_level(i2c_port->sda, 1);
- i2c_delay();
-
- /* Check if the bus is unwedged. */
- if (gpio_get_level(i2c_port->sda) &&
- gpio_get_level(i2c_port->scl))
- break;
- }
-
- if (!gpio_get_level(i2c_port->sda))
- CPUTS("I2C unwedge failed, SDA still low\n");
- if (!gpio_get_level(i2c_port->scl))
- CPUTS("I2C unwedge failed, SCL still low\n");
-}
-
-static void i2c_stop_cond(const struct i2c_port_t *i2c_port)
-{
- int i;
-
- if (!started)
- return;
-
- gpio_set_level(i2c_port->sda, 0);
- i2c_delay();
-
- gpio_set_level(i2c_port->scl, 1);
-
- /*
- * SMBus 3.0, 4.2.5
- *
- * the recommendation is that if SMBDAT is still low tTIMEOUT,MAX after
- * SMBCLK has gone high at the end of a transaction the controller
- * should hold SMBCLK low for at least tTIMEOUT,MAX in an attempt to
- * reset the SMBus interface of all of the devices on the bus.
- */
- for (i = 0; i < 7000; i++) {
- if (gpio_get_level(i2c_port->scl))
- break;
- i2c_delay();
- }
- i2c_delay();
-
- /* SCL is high, set SDA from 0 to 1 */
- gpio_set_level(i2c_port->sda, 1);
- i2c_delay();
-
- started = 0;
-}
-
-static int clock_stretching(const struct i2c_port_t *i2c_port)
-{
- int i;
-
- i2c_delay();
- /* 5us * 7000 iterations ~= 35ms */
- for (i = 0; i < 7000; i++) {
- if (gpio_get_level(i2c_port->scl))
- return 0;
- i2c_delay();
- }
-
- /*
- * SMBus 3.0, Note 3
- * Devices participating in a transfer can abort the transfer in
- * progress and release the bus when any single clock low interval
- * exceeds the value of tTIMEOUT,MIN(=25ms).
- * After the controller in a transaction detects this condition, it must
- * generate a stop condition within or after the current data byte in
- * the transfer process.
- */
- i2c_stop_cond(i2c_port);
- CPUTS("clock low timeout\n");
-
- return EC_ERROR_TIMEOUT;
-}
-
-static int i2c_start_cond(const struct i2c_port_t *i2c_port)
-{
- int err;
-
- if (started) {
- gpio_set_level(i2c_port->sda, 1);
- i2c_delay();
-
- gpio_set_level(i2c_port->scl, 1);
- err = clock_stretching(i2c_port);
- if (err)
- return err;
- i2c_delay();
-
- if (gpio_get_level(i2c_port->sda) == 0) {
- CPUTS("start_cond: arbitration lost\n");
- started = 0;
- return EC_ERROR_UNKNOWN;
- }
- }
-
- /* check if bus is idle before starting */
- if (gpio_get_level(i2c_port->scl) == 0 ||
- gpio_get_level(i2c_port->sda) == 0)
- return EC_ERROR_UNKNOWN;
-
- gpio_set_level(i2c_port->sda, 0);
- i2c_delay();
-
- gpio_set_level(i2c_port->scl, 0);
- started = 1;
-
- return 0;
-}
-
-static int i2c_write_bit(const struct i2c_port_t *i2c_port, int bit)
-{
- int err;
-
- gpio_set_level(i2c_port->sda, !!bit);
- i2c_delay();
-
- gpio_set_level(i2c_port->scl, 1);
- err = clock_stretching(i2c_port);
- if (err)
- return err;
- i2c_delay();
-
- if (bit && gpio_get_level(i2c_port->sda) == 0) {
- CPUTS("write_bit: arbitration lost\n");
- started = 0;
- return EC_ERROR_UNKNOWN;
- }
-
- gpio_set_level(i2c_port->scl, 0);
-
- return 0;
-}
-
-static int i2c_read_bit(const struct i2c_port_t *i2c_port, int *bit)
-{
- int err;
-
- gpio_set_level(i2c_port->sda, 1);
- i2c_delay();
-
- gpio_set_level(i2c_port->scl, 1);
- err = clock_stretching(i2c_port);
- if (err)
- return err;
- i2c_delay();
- *bit = gpio_get_level(i2c_port->sda);
-
- gpio_set_level(i2c_port->scl, 0);
-
- return 0;
-}
-
-static int i2c_write_byte(const struct i2c_port_t *i2c_port, uint8_t byte)
-{
- int i, nack, err;
-
- for (i = 7; i >= 0; i--) {
- err = i2c_write_bit(i2c_port, byte & (1 << i));
- if (err)
- return err;
- }
-
- err = i2c_read_bit(i2c_port, &nack);
- if (err)
- return err;
-
- if (nack) {
- /*
- * The peripheral device detects an invalid command or invalid
- * data. In this case the peripheral device must NACK the
- * received byte. The controller upon detection of this
- * condition must generate a STOP condition and retry the
- * transaction
- */
- i2c_stop_cond(i2c_port);
- /* return EC_ERROR_BUSY to indicate i2c_xfer() to retry */
- return EC_ERROR_BUSY;
- }
- return 0;
-}
-
-static int i2c_read_byte(const struct i2c_port_t *i2c_port, uint8_t *byte,
- int nack)
-{
- int i;
-
- *byte = 0;
- for (i = 0; i < 8; i++) {
- int bit = 0, err;
-
- err = i2c_read_bit(i2c_port, &bit);
- if (err)
- return err;
- *byte = (*byte << 1) | bit;
- }
-
- return i2c_write_bit(i2c_port, nack);
-}
-
-static int i2c_bitbang_xfer(const struct i2c_port_t *i2c_port,
- const uint16_t addr_flags,
- const uint8_t *out, int out_size,
- uint8_t *in, int in_size, int flags)
-{
- uint16_t addr_8bit = addr_flags << 1, err = EC_SUCCESS;
- int i = 0;
-
- if (i2c_port->kbps != 100)
- CPUTS("warning: bitbang driver only supports 100kbps\n");
-
- if (out_size) {
- if (flags & I2C_XFER_START) {
- err = i2c_start_cond(i2c_port);
- if (err)
- goto exit;
- err = i2c_write_byte(i2c_port, addr_8bit);
- if (err)
- goto exit;
- }
-
- for (i = 0; i < out_size; i++) {
- err = i2c_write_byte(i2c_port, out[i]);
- if (err)
- goto exit;
- }
- }
-
- if (in_size) {
- if (flags & I2C_XFER_START) {
- err = i2c_start_cond(i2c_port);
- if (err)
- goto exit;
- err = i2c_write_byte(i2c_port, addr_8bit | 1);
- if (err)
- goto exit;
- }
-
- for (i = 0; i < in_size; i++) {
- err = i2c_read_byte(i2c_port, &in[i],
- (flags & I2C_XFER_STOP) && (i == in_size - 1));
- if (err)
- goto exit;
- }
- }
-
- if (flags & I2C_XFER_STOP)
- i2c_stop_cond(i2c_port);
-
-exit:
- if (err) {
- i2c_bitbang_unwedge(i2c_port);
- started = 0;
- }
- return err;
-}
-
-const struct i2c_drv bitbang_drv = {
- .xfer = &i2c_bitbang_xfer
-};
-
-#ifdef TEST_BUILD
-int bitbang_start_cond(const struct i2c_port_t *i2c_port)
-{
- return i2c_start_cond(i2c_port);
-}
-
-void bitbang_stop_cond(const struct i2c_port_t *i2c_port)
-{
- i2c_stop_cond(i2c_port);
-}
-
-int bitbang_write_byte(const struct i2c_port_t *i2c_port, uint8_t byte)
-{
- return i2c_write_byte(i2c_port, byte);
-}
-
-void bitbang_set_started(int val)
-{
- started = val;
-}
-#endif
diff --git a/common/i2c_hid_touchpad.c b/common/i2c_hid_touchpad.c
deleted file mode 100644
index 29122f83d6..0000000000
--- a/common/i2c_hid_touchpad.c
+++ /dev/null
@@ -1,797 +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.
- */
-
-#include "i2c_hid_touchpad.h"
-
-#include "console.h"
-#include "hwtimer.h"
-#include "util.h"
-
-/* 2 bytes for length + 1 byte for report ID */
-#define I2C_HID_HEADER_SIZE 3
-
-/* Report ID */
-#define REPORT_ID_TOUCH 0x01
-#define REPORT_ID_MOUSE 0x02
-#define REPORT_ID_DEVICE_CAPS 0x0A
-#define REPORT_ID_DEVICE_CERT 0x0B
-#define REPORT_ID_INPUT_MODE 0x0C
-#define REPORT_ID_REPORTING 0x0D
-
-#define INPUT_MODE_MOUSE 0x00
-#define INPUT_MODE_TOUCH 0x03
-
-/* VID/PID/FW version */
-#if !defined(I2C_HID_TOUCHPAD_VENDOR_ID) || \
- !defined(I2C_HID_TOUCHPAD_PRODUCT_ID) || \
- !defined(I2C_HID_TOUCHPAD_FW_VERSION)
-#error "Must define touchpad VID/PID/FW version"
-#endif
-/*
- * Touchpad properties
- *
- * Physical dimensions are in the unit of mms.
- */
-#if !defined(I2C_HID_TOUCHPAD_MAX_X) || \
- !defined(I2C_HID_TOUCHPAD_MAX_Y) || \
- !defined(I2C_HID_TOUCHPAD_MAX_PHYSICAL_X) || \
- !defined(I2C_HID_TOUCHPAD_MAX_PHYSICAL_Y)
-#error "Must define finger maximum X/Y and physical dimensions"
-#endif
-/*
- * Maximum width/height of the contact (i.e., touch major/minor in Linux MT-B)
- *
- * According to the Linux's MT protocol, the max value of touch major/minor
- * should be sqrt(X^2+Y^2). However, this is rarely implemented by touchpads
- * in practice. Touchpads often output major/minor in custom units with very
- * different data ranges. It is therefore recommended for the user to check the
- * device's spec and set these values manually.
- */
-#if !defined(I2C_HID_TOUCHPAD_MAX_WIDTH) || \
- !defined(I2C_HID_TOUCHPAD_MAX_HEIGHT) || \
- !defined(I2C_HID_TOUCHPAD_MAX_PRESSURE)
-#error "Must define finger maximum width/height/pressure"
-#endif
-/*
- * The touchpad is expected to provide at least the horizontal/vertical status
- * for each contact (if one is wider than its height). This can be computed
- * simply as bool(WIDTH>HEIGHT).
- */
-#ifndef I2C_HID_TOUCHPAD_MAX_ORIENTATION
-#error "Must define finger maximum orientation value"
-#endif
-/*
- * Conversion factor between the finger movement and the mouse cursor movement.
- * This is a bit similar to the mouse CPI and is used by mouse reports only.
- */
-#if !defined(I2C_HID_TOUCHPAD_MOUSE_SCALE_X) || \
- !defined(I2C_HID_TOUCHPAD_MOUSE_SCALE_Y)
-#error "Must define mouse horizontal/vertical scaling factors"
-#endif
-
-/* Helper bit-op macros */
-#define N_BITS(n) \
-( \
- (n) < (1 << 1) ? 1 : \
- (n) < (1 << 2) ? 2 : \
- (n) < (1 << 3) ? 3 : \
- (n) < (1 << 4) ? 4 : \
- (n) < (1 << 5) ? 5 : \
- (n) < (1 << 6) ? 6 : \
- (n) < (1 << 7) ? 7 : \
- (n) < (1 << 8) ? 8 : \
- (n) < (1 << 9) ? 9 : \
- (n) < (1 << 10) ? 10 : \
- (n) < (1 << 11) ? 11 : \
- (n) < (1 << 12) ? 12 : \
- (n) < (1 << 13) ? 13 : \
- (n) < (1 << 14) ? 14 : \
- (n) < (1 << 15) ? 15 : \
- 16 \
-)
-/* We would need to pad some bits at the end of each finger struct to match
- * the allocation unit's boundary so the array indexing may work correctly.
- */
-#define N_VAR_BITS \
-( \
- N_BITS(I2C_HID_TOUCHPAD_MAX_X) + \
- N_BITS(I2C_HID_TOUCHPAD_MAX_Y) + \
- N_BITS(I2C_HID_TOUCHPAD_MAX_WIDTH) + \
- N_BITS(I2C_HID_TOUCHPAD_MAX_HEIGHT) + \
- N_BITS(I2C_HID_TOUCHPAD_MAX_PRESSURE) + \
- N_BITS(I2C_HID_TOUCHPAD_MAX_ORIENTATION) \
-)
-#define N_PADDING_BITS ((DIV_ROUND_UP(N_VAR_BITS, 8) * 8) - N_VAR_BITS)
-#define N_BITS_ORIENTATION \
- (N_BITS(I2C_HID_TOUCHPAD_MAX_ORIENTATION) + N_PADDING_BITS)
-/* Structs for holding input report data
- *
- * These need to be modified in correspondence with the HID input report
- * descriptor below.
- *
- * The HID usage names differ from the Evdev event names in some cases. For
- * example, touch major/minor are put under width/height and orientation is
- * called azimuth.
- */
-struct finger {
- /*
- * Whether a finger is intentional or not. This could be used to
- * identify unintended contacts or palms but is up to the OS
- * explanation.
- */
- uint8_t confidence:1;
- /*
- * Whether a finger is touching the surface (leaving/left finger gets
- * 0).
- */
- uint8_t tip:1;
- /*
- * Whether a finger is within the sensor range. For example, hovering
- * fingers would have tip=0 and inrange=1.
- */
- uint8_t inrange:1;
- /*
- * Contact id. This is like slot numbers in Linux MT-B.
- */
- uint8_t id:5;
- uint16_t x:N_BITS(I2C_HID_TOUCHPAD_MAX_X);
- uint16_t y:N_BITS(I2C_HID_TOUCHPAD_MAX_Y);
- uint16_t width:N_BITS(I2C_HID_TOUCHPAD_MAX_WIDTH);
- uint16_t height:N_BITS(I2C_HID_TOUCHPAD_MAX_HEIGHT);
- uint16_t pressure:N_BITS(I2C_HID_TOUCHPAD_MAX_PRESSURE);
- uint16_t orientation:N_BITS_ORIENTATION;
-} __packed;
-
-struct touch_report {
- uint8_t button:1;
- uint8_t count:7;
- uint16_t timestamp;
- struct finger finger[I2C_HID_TOUCHPAD_MAX_FINGERS];
-} __packed;
-
-struct mouse_report {
- uint8_t button1:1;
- /* Windows expects at least two button usages in a mouse report. Many
- * touchpads on the Chromebook are a single clickable surface, so
- * button2 isn't used. That said, we may later report a button2 event if
- * necessary.
- */
- uint8_t button2:1;
- uint8_t unused:6;
- int8_t x;
- int8_t y;
-} __packed;
-
-/* HID input report descriptor
- *
- * For a complete reference, please see the following docs on usb.org
- *
- * 1. Device Class Definition for HID
- * 2. HID Usage Tables
- */
-static const uint8_t report_desc[] = {
- /* Mouse Collection */
- 0x05, 0x01, /* Usage Page (Generic Desktop) */
- 0x09, 0x02, /* Usage (Mouse) */
- 0xA1, 0x01, /* Collection (Application) */
- 0x85, REPORT_ID_MOUSE, /* Report ID (Mouse) */
- 0x09, 0x01, /* Usage (Pointer) */
- 0xA1, 0x00, /* Collection (Physical) */
- 0x05, 0x09, /* Usage Page (Button) */
- 0x19, 0x01, /* Usage Minimum (Button 1) */
- 0x29, 0x02, /* Usage Maximum (Button 2) */
- 0x15, 0x00, /* Logical Minimum (0) */
- 0x25, 0x01, /* Logical Maximum (1) */
- 0x75, 0x01, /* Report Size (1) */
- 0x95, 0x02, /* Report Count (2) */
- 0x81, 0x02, /* Input (Data,Var,Abs) */
- 0x95, 0x06, /* Report Count (6) */
- 0x81, 0x03, /* Input (Cnst,Var,Abs) */
- 0x05, 0x01, /* Usage Page (Generic Desktop) */
- 0x09, 0x30, /* Usage (X) */
- 0x09, 0x31, /* Usage (Y) */
- 0x15, 0x81, /* Logical Minimum (-127) */
- 0x25, 0x7F, /* Logical Maximum (127) */
- 0x75, 0x08, /* Report Size (8) */
- 0x95, 0x02, /* Report Count (2) */
- 0x81, 0x06, /* Input (Data,Var,Rel) */
- 0xC0, /* End Collection */
- 0xC0, /* End Collection */
-
- /* Touchpad Collection */
- 0x05, 0x0D, /* Usage Page (Digitizer) */
- 0x09, 0x05, /* Usage (Touch Pad) */
- 0xA1, 0x01, /* Collection (Application) */
- 0x85, REPORT_ID_TOUCH, /* Report ID (Touch) */
-
- /* Button */
- 0x05, 0x09, /* Usage Page (Button) */
- 0x19, 0x01, /* Usage Minimum (0x01) */
- 0x29, 0x01, /* Usage Maximum (0x01) */
- 0x15, 0x00, /* Logical Minimum (0) */
- 0x25, 0x01, /* Logical Maximum (1) */
- 0x75, 0x01, /* Report Size (1) */
- 0x95, 0x01, /* Report Count (1) */
- 0x81, 0x02, /* Input (Data,Var,Abs) */
-
- /* Contact count */
- 0x05, 0x0D, /* Usage Page (Digitizer) */
- 0x09, 0x54, /* Usage (Contact count) */
- 0x25, I2C_HID_TOUCHPAD_MAX_FINGERS, /* Logical Max. (MAX_FINGERS) */
- 0x75, 0x07, /* Report Size (7) */
- 0x95, 0x01, /* Report Count (1) */
- 0x81, 0x02, /* Input (Data,Var,Abs) */
-
- /* Scan time */
- 0x55, 0x0C, /* Unit Exponent (-4) */
- 0x66, 0x01, 0x10, /* Unit (Seconds) */
- 0x47, 0xFF, 0xFF, 0x00, 0x00, /* Physical Maximum (65535) */
- 0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum (65535) */
- 0x75, 0x10, /* Report Size (16) */
- 0x95, 0x01, /* Report Count (1) */
- 0x05, 0x0D, /* Usage Page (Digitizers) */
- 0x09, 0x56, /* Usage (Scan Time) */
- 0x81, 0x02, /* Input (Data,Var,Abs) */
-
-#define FINGER(FINGER_NUMBER) \
- /* Finger FINGER_NUMBER */ \
- 0x05, 0x0D, /* Usage Page (Digitizer) */ \
- 0x09, 0x22, /* Usage (Finger) */ \
- 0xA1, 0x02, /* Collection (Logical) */ \
- 0x09, 0x47, /* Usage (Confidence) */ \
- 0x09, 0x42, /* Usage (Tip Switch) */ \
- 0x09, 0x32, /* Usage (In Range) */ \
- 0x15, 0x00, /* Logical Minimum (0) */ \
- 0x25, 0x01, /* Logical Maximum (1) */ \
- 0x75, 0x01, /* Report Size (1) */ \
- 0x95, 0x03, /* Report Count (3) */ \
- 0x81, 0x02, /* Input (Data,Var,Abs) */ \
- 0x09, 0x51, /* Usage (Contact identifier) */ \
- 0x25, 0x1F, /* Logical Maximum (31) */ \
- 0x75, 0x05, /* Report Size (5) */ \
- 0x95, 0x01, /* Report Count (1) */ \
- 0x81, 0x02, /* Input (Data,Var,Abs) */ \
- 0x05, 0x01, /* Usage Page (Generic Desktop) */ \
- 0x09, 0x30, /* Usage (X) */ \
- 0x55, 0x0E, /* Unit Exponent (-2) */ \
- 0x65, 0x11, /* Unit (SI Linear, Length: cm) */ \
- 0x35, 0x00, /* Physical Minimum (0) */ \
- 0x46, I2C_HID_TOUCHPAD_MAX_PHYSICAL_X&0xff, \
- I2C_HID_TOUCHPAD_MAX_PHYSICAL_X>>8, \
- /* Physical Maximum */ \
- 0x26, I2C_HID_TOUCHPAD_MAX_X&0xff, I2C_HID_TOUCHPAD_MAX_X>>8, \
- /* Logical Maximum */ \
- 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_X), \
- /* Report Size */ \
- 0x81, 0x02, /* Input (Data,Var,Abs) */ \
- 0x09, 0x31, /* Usage (Y) */ \
- 0x46, I2C_HID_TOUCHPAD_MAX_PHYSICAL_Y&0xff, \
- I2C_HID_TOUCHPAD_MAX_PHYSICAL_Y>>8, \
- /* Physical Maximum */ \
- 0x26, I2C_HID_TOUCHPAD_MAX_Y&0xff, I2C_HID_TOUCHPAD_MAX_Y>>8, \
- /* Logical Maximum */ \
- 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_Y), \
- /* Report Size */ \
- 0x81, 0x02, /* Input (Data,Var,Abs) */ \
- 0x05, 0x0D, /* Usage Page (Digitizer) */ \
- 0x09, 0x48, /* Usage (Width) */ \
- 0x26, I2C_HID_TOUCHPAD_MAX_WIDTH&0xff, I2C_HID_TOUCHPAD_MAX_WIDTH>>8, \
- /* Logical Maximum */ \
- 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_WIDTH), \
- /* Report Size */ \
- 0x81, 0x02, /* Input (Data,Var,Abs) */ \
- 0x09, 0x49, /* Usage (Height) */ \
- 0x26, I2C_HID_TOUCHPAD_MAX_HEIGHT&0xff, I2C_HID_TOUCHPAD_MAX_HEIGHT>>8,\
- /* Logical Maximum */ \
- 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_HEIGHT), \
- /* Report Size */ \
- 0x81, 0x02, /* Input (Data,Var,Abs) */ \
- 0x09, 0x30, /* Usage (Tip pressure) */ \
- 0x26, I2C_HID_TOUCHPAD_MAX_PRESSURE&0xff, \
- I2C_HID_TOUCHPAD_MAX_PRESSURE>>8, \
- /* Logical Maximum */ \
- 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_PRESSURE), \
- /* Report Size */ \
- 0x81, 0x02, /* Input (Data,Var,Abs) */ \
- 0x09, 0x3f, /* Usage (Azimuth Orientation) */ \
- 0x16, 0x00, 0x00, /* Logical Minimum (0) */ \
- 0x26, I2C_HID_TOUCHPAD_MAX_ORIENTATION&0xff, \
- I2C_HID_TOUCHPAD_MAX_ORIENTATION>>8, \
- /* Logical Maximum */ \
- 0x75, N_BITS_ORIENTATION, /* Report Size */ \
- 0x81, 0x02, /* Input (Data,Var,Abs) */ \
- 0xC0, /* End Collection */
-
- FINGER(1)
- FINGER(2)
- FINGER(3)
- FINGER(4)
- FINGER(5)
-
-#undef FINGER
-
- 0x05, 0x0D, /* Usage Page (Digitizer) */
- 0x85, REPORT_ID_DEVICE_CAPS, /* Report ID (Device Capabilities) */
- 0x09, 0x55, /* Usage (Contact Count Maximum) */
- 0x09, 0x59, /* Usage (Pad Type) */
- 0x75, 0x08, /* Report Size (8) */
- 0x95, 0x02, /* Report Count (2) */
- 0x25, 0x0F, /* Logical Maximum (15) */
- 0xB1, 0x02, /* Feature (Data,Var,Abs) */
- 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined) */
- 0x85, REPORT_ID_DEVICE_CERT, /* Report ID (Device Certification) */
- 0x09, 0xC5, /* Usage (Vendor Usage 0xC5) */
- 0x15, 0x00, /* Logical Minimum (0) */
- 0x26, 0xFF, 0x00, /* Logical Maximum (255) */
- 0x75, 0x08, /* Report Size (8) */
- 0x96, 0x00, 0x01, /* Report Count (256) */
- 0xB1, 0x02, /* Feature (Data,Var,Abs) */
- 0xC0, /* End Collection */
-
- /* Configuration Collection */
- 0x05, 0x0D, /* Usage Page (Digitizer) */
- 0x09, 0x0E, /* Usage (Configuration) */
- 0xA1, 0x01, /* Collection (Application) */
- 0x85, REPORT_ID_INPUT_MODE, /* Report ID (Input Mode) */
- 0x09, 0x22, /* Usage (Finger) */
- 0xA1, 0x02, /* Collection (Logical) */
- 0x09, 0x52, /* Usage (Input Mode) */
- 0x15, 0x00, /* Logical Minimum (0) */
- 0x25, 0x0F, /* Logical Maximum (15) */
- 0x75, 0x08, /* Report Size (8) */
- 0x95, 0x01, /* Report Count (1) */
- 0xB1, 0x02, /* Feature (Data,Var,Abs) */
- 0xC0, /* End Collection */
- 0x09, 0x22, /* Usage (Finger) */
- 0xA1, 0x00, /* Collection (Physical) */
- 0x85, REPORT_ID_REPORTING, /* Report ID (Selective Reporting)*/
- 0x09, 0x57, /* Usage (Surface Switch) */
- 0x09, 0x58, /* Usage (Button Switch) */
- 0x75, 0x04, /* Report Size (4) */
- 0x95, 0x02, /* Report Count (2) */
- 0x25, 0x01, /* Logical Maximum (1) */
- 0xB1, 0x02, /* Feature (Data,Var,Abs) */
- 0xC0, /* End Collection */
- 0xC0, /* End Collection */
-};
-
-static const uint8_t device_caps[] = {
- I2C_HID_TOUCHPAD_MAX_FINGERS, /* Contact Count Maximum */
- 0x00, /* Pad Type: Depressible click-pad */
-};
-
-/* A 256-byte default blob for the 'device certification status' feature report
- * expected by Windows.
- */
-static const uint8_t device_cert[] = {
- 0xFC, 0x28, 0xFE, 0x84, 0x40, 0xCB, 0x9A, 0x87,
- 0x0D, 0xBE, 0x57, 0x3C, 0xB6, 0x70, 0x09, 0x88,
- 0x07, 0x97, 0x2D, 0x2B, 0xE3, 0x38, 0x34, 0xB6,
- 0x6C, 0xED, 0xB0, 0xF7, 0xE5, 0x9C, 0xF6, 0xC2,
- 0x2E, 0x84, 0x1B, 0xE8, 0xB4, 0x51, 0x78, 0x43,
- 0x1F, 0x28, 0x4B, 0x7C, 0x2D, 0x53, 0xAF, 0xFC,
- 0x47, 0x70, 0x1B, 0x59, 0x6F, 0x74, 0x43, 0xC4,
- 0xF3, 0x47, 0x18, 0x53, 0x1A, 0xA2, 0xA1, 0x71,
- 0xC7, 0x95, 0x0E, 0x31, 0x55, 0x21, 0xD3, 0xB5,
- 0x1E, 0xE9, 0x0C, 0xBA, 0xEC, 0xB8, 0x89, 0x19,
- 0x3E, 0xB3, 0xAF, 0x75, 0x81, 0x9D, 0x53, 0xB9,
- 0x41, 0x57, 0xF4, 0x6D, 0x39, 0x25, 0x29, 0x7C,
- 0x87, 0xD9, 0xB4, 0x98, 0x45, 0x7D, 0xA7, 0x26,
- 0x9C, 0x65, 0x3B, 0x85, 0x68, 0x89, 0xD7, 0x3B,
- 0xBD, 0xFF, 0x14, 0x67, 0xF2, 0x2B, 0xF0, 0x2A,
- 0x41, 0x54, 0xF0, 0xFD, 0x2C, 0x66, 0x7C, 0xF8,
- 0xC0, 0x8F, 0x33, 0x13, 0x03, 0xF1, 0xD3, 0xC1,
- 0x0B, 0x89, 0xD9, 0x1B, 0x62, 0xCD, 0x51, 0xB7,
- 0x80, 0xB8, 0xAF, 0x3A, 0x10, 0xC1, 0x8A, 0x5B,
- 0xE8, 0x8A, 0x56, 0xF0, 0x8C, 0xAA, 0xFA, 0x35,
- 0xE9, 0x42, 0xC4, 0xD8, 0x55, 0xC3, 0x38, 0xCC,
- 0x2B, 0x53, 0x5C, 0x69, 0x52, 0xD5, 0xC8, 0x73,
- 0x02, 0x38, 0x7C, 0x73, 0xB6, 0x41, 0xE7, 0xFF,
- 0x05, 0xD8, 0x2B, 0x79, 0x9A, 0xE2, 0x34, 0x60,
- 0x8F, 0xA3, 0x32, 0x1F, 0x09, 0x78, 0x62, 0xBC,
- 0x80, 0xE3, 0x0F, 0xBD, 0x65, 0x20, 0x08, 0x13,
- 0xC1, 0xE2, 0xEE, 0x53, 0x2D, 0x86, 0x7E, 0xA7,
- 0x5A, 0xC5, 0xD3, 0x7D, 0x98, 0xBE, 0x31, 0x48,
- 0x1F, 0xFB, 0xDA, 0xAF, 0xA2, 0xA8, 0x6A, 0x89,
- 0xD6, 0xBF, 0xF2, 0xD3, 0x32, 0x2A, 0x9A, 0xE4,
- 0xCF, 0x17, 0xB7, 0xB8, 0xF4, 0xE1, 0x33, 0x08,
- 0x24, 0x8B, 0xC4, 0x43, 0xA5, 0xE5, 0x24, 0xC2,
-};
-
-#define MAX_SIZEOF(a, b) (sizeof(a) > sizeof(b) ? sizeof(a) : sizeof(b))
-
-static struct i2c_hid_descriptor hid_desc = {
- .wHIDDescLength = I2C_HID_DESC_LENGTH,
- .bcdVersion = I2C_HID_BCD_VERSION,
- .wReportDescLength = sizeof(report_desc),
- .wReportDescRegister = I2C_HID_REPORT_DESC_REGISTER,
- .wInputRegister = I2C_HID_INPUT_REPORT_REGISTER,
- .wMaxInputLength = I2C_HID_HEADER_SIZE +
- MAX_SIZEOF(struct touch_report, struct mouse_report),
- .wOutputRegister = 0,
- .wMaxOutputLength = 0,
- .wCommandRegister = I2C_HID_COMMAND_REGISTER,
- .wDataRegister = I2C_HID_DATA_REGISTER,
- .wVendorID = I2C_HID_TOUCHPAD_VENDOR_ID,
- .wProductID = I2C_HID_TOUCHPAD_PRODUCT_ID,
- .wVersionID = I2C_HID_TOUCHPAD_FW_VERSION,
-};
-
-/*
- * In I2C HID, the host would request for an input report immediately following
- * the protocol initialization. The device is required to respond with exactly
- * 2 empty bytes. Furthermore, some hosts may use a single byte SMBUS read to
- * check if the device exists on the specified I2C address.
- *
- * These variables record if such probing/initialization have been done before.
- */
-static bool pending_probe;
-static bool pending_reset;
-
-/* Reports (double buffered) */
-#define MAX_REPORT_CNT 2
-
-static struct touch_report touch_reports[MAX_REPORT_CNT];
-static struct mouse_report mouse_reports[MAX_REPORT_CNT];
-
-/* Current active report buffer index */
-static int report_active_index;
-
-/* Current input mode */
-static uint8_t input_mode;
-
-/*
- * TODO(b/151693566): Selectively report surface contact and button state in
- * input reports based on |reporting.surface_switch| and
- * |reporting.button_switch|, respectively.
- */
-struct selective_reporting {
- uint8_t surface_switch:4;
- uint8_t button_switch:4;
-} __packed;
-
-static struct selective_reporting reporting;
-
-/* Function declarations */
-static int i2c_hid_touchpad_command_process(size_t len, uint8_t *buffer,
- void (*send_response)(int len),
- uint8_t *data);
-
-static size_t fill_report(uint8_t *buffer, uint8_t report_id, const void *data,
- size_t data_len)
-{
- size_t response_len = I2C_HID_HEADER_SIZE + data_len;
-
- buffer[0] = response_len & 0xFF;
- buffer[1] = (response_len >> 8) & 0xFF;
- buffer[2] = report_id;
- memcpy(buffer + I2C_HID_HEADER_SIZE, data, data_len);
- return response_len;
-}
-
-/*
- * Extracts report data from |buffer| into |data| for reports from the host.
- *
- * |buffer| is expected to contain the values written to the command register
- * followed by the values written to the data register, upon receiving a
- * SET_REPORT command, in the following byte sequence format:
- *
- * 00 30 - command register address (0x3000)
- * xx - report type and ID
- * 03 - SET_REPORT
- * 00 30 - data register address (0x3000)
- * xx xx - length
- * xx - report ID
- * xx... - report data
- *
- * Note that command register and data register have the same address. Also,
- * any report ID >= 15 requires an extra byte after the SET_REPORT byte, which
- * is not supported here as we don't have any report ID >= 15.
- *
- * In summary, we expect |buffer| contains at least 10 bytes where the report
- * data starts at buffer[9]. If |buffer| contains the incorrect number bytes,
- * we ignore the report.
- */
-static void extract_report(size_t len, const uint8_t *buffer, void *data,
- size_t data_len)
-{
- if (len != 9 + data_len) {
- ccprints("I2C-HID: SET_REPORT buffer length mismatch");
- return;
- }
- memcpy(data, buffer + 9, data_len);
-}
-
-void i2c_hid_touchpad_init(void)
-{
- input_mode = INPUT_MODE_MOUSE;
- reporting.surface_switch = 1;
- reporting.button_switch = 1;
- report_active_index = 0;
-
- // Respond probing requests for now.
- pending_probe = true;
- pending_reset = false;
-}
-
-int i2c_hid_touchpad_process(unsigned int len, uint8_t *buffer,
- void (*send_response)(int len), uint8_t *data,
- int *reg, int *cmd)
-{
- size_t response_len;
-
- if (len == 0)
- *reg = I2C_HID_INPUT_REPORT_REGISTER;
- else
- *reg = UINT16_FROM_BYTE_ARRAY_LE(buffer, 0);
-
- *cmd = 0;
- switch (*reg) {
- case I2C_HID_HID_DESC_REGISTER:
- memcpy(buffer, &hid_desc, sizeof(hid_desc));
- send_response(sizeof(hid_desc));
- break;
- case I2C_HID_REPORT_DESC_REGISTER:
- memcpy(buffer, &report_desc, sizeof(report_desc));
- send_response(sizeof(report_desc));
- break;
- case I2C_HID_INPUT_REPORT_REGISTER:
- // Single-byte read probing.
- if (pending_probe) {
- buffer[0] = 0;
- send_response(1);
- break;
- }
- // Reset protocol: 2 empty bytes.
- if (pending_reset) {
- pending_reset = false;
- buffer[0] = 0;
- buffer[1] = 0;
- send_response(2);
- break;
- }
- // Common input report requests.
- if (input_mode == INPUT_MODE_TOUCH) {
- response_len =
- fill_report(buffer, REPORT_ID_TOUCH,
- &touch_reports[report_active_index],
- sizeof(struct touch_report));
- } else {
- response_len =
- fill_report(buffer, REPORT_ID_MOUSE,
- &mouse_reports[report_active_index],
- sizeof(struct mouse_report));
- }
- send_response(response_len);
- break;
- case I2C_HID_COMMAND_REGISTER:
- *cmd = i2c_hid_touchpad_command_process(len, buffer,
- send_response, data);
- break;
- default:
- /* Unknown register has been received. */
- return EC_ERROR_INVAL;
- }
- /* Unknown command has been received. */
- if (*cmd < 0)
- return EC_ERROR_INVAL;
- return EC_SUCCESS;
-}
-
-static int i2c_hid_touchpad_command_process(size_t len, uint8_t *buffer,
- void (*send_response)(int len),
- uint8_t *data)
-{
- uint8_t command = buffer[3] & 0x0F;
- uint8_t power_state = buffer[2] & 0x03;
- uint8_t report_id = buffer[2] & 0x0F;
- size_t response_len;
-
- switch (command) {
- case I2C_HID_CMD_RESET:
- i2c_hid_touchpad_init();
- // Wait for the 2-bytes I2C read following the protocol reset.
- pending_probe = false;
- pending_reset = true;
- break;
- case I2C_HID_CMD_GET_REPORT:
- switch (report_id) {
- case REPORT_ID_TOUCH:
- response_len =
- fill_report(buffer, report_id,
- &touch_reports[report_active_index],
- sizeof(struct touch_report));
- break;
- case REPORT_ID_MOUSE:
- response_len =
- fill_report(buffer, report_id,
- &mouse_reports[report_active_index],
- sizeof(struct mouse_report));
- break;
- case REPORT_ID_DEVICE_CAPS:
- response_len = fill_report(buffer, report_id,
- &device_caps,
- sizeof(device_caps));
- break;
- case REPORT_ID_DEVICE_CERT:
- response_len = fill_report(buffer, report_id,
- &device_cert,
- sizeof(device_cert));
- break;
- case REPORT_ID_INPUT_MODE:
- response_len = fill_report(buffer, report_id,
- &input_mode,
- sizeof(input_mode));
- break;
- case REPORT_ID_REPORTING:
- response_len = fill_report(buffer, report_id,
- &reporting,
- sizeof(reporting));
- break;
- default:
- response_len = 2;
- buffer[0] = response_len;
- buffer[1] = 0;
- break;
- }
- send_response(response_len);
- break;
- case I2C_HID_CMD_SET_REPORT:
- switch (report_id) {
- case REPORT_ID_INPUT_MODE:
- extract_report(len, buffer, &input_mode,
- sizeof(input_mode));
- break;
- case REPORT_ID_REPORTING:
- extract_report(len, buffer, &reporting,
- sizeof(reporting));
- break;
- default:
- break;
- }
- break;
- case I2C_HID_CMD_SET_POWER:
- /*
- * Return the power setting so the user can actually set the
- * touch controller's power state in board level.
- */
- *data = power_state;
- break;
- default:
- return -1;
- }
- return command;
-}
-
-void i2c_hid_compile_report(struct touchpad_event *event)
-{
- /* Save report into back buffer */
- struct touch_report *touch = &touch_reports[report_active_index ^ 1];
- struct touch_report *touch_old = &touch_reports[report_active_index];
- struct mouse_report *mouse = &mouse_reports[report_active_index ^ 1];
- int contact_num = 0;
-
- /* Touch report. */
- memset(touch, 0, sizeof(struct touch_report));
- for (int i = 0; i < I2C_HID_TOUCHPAD_MAX_FINGERS; i++) {
- if (event->finger[i].valid) {
- /*
- * Windows considers any contact with width or height
- * greater than 25mm to unintended, and expects the
- * confidence value to be cleared for such a contact.
- * We, however, haven't seen a touchpad that actually
- * forwards that information to us.
- *
- * TODO(b/151692377): Revisit this once we have met such
- * a device.
- */
- touch->finger[i].confidence = 1;
- touch->finger[i].tip = 1;
- touch->finger[i].inrange = 1;
- touch->finger[i].x = event->finger[i].x;
- touch->finger[i].y = event->finger[i].y;
- touch->finger[i].width = event->finger[i].width;
- touch->finger[i].height = event->finger[i].height;
- touch->finger[i].pressure = event->finger[i].pressure;
- if (event->finger[i].is_palm)
- touch->finger[i].pressure =
- I2C_HID_TOUCHPAD_MAX_PRESSURE;
- touch->finger[i].orientation =
- event->finger[i].orientation;
- contact_num++;
- } else if (touch_old->finger[i].tip) {
- /*
- * When the finger is leaving, we first clear the tip
- * bit while retaining the other values. We then clear
- * the other values at the next frame where the finger
- * has left.
- *
- * Setting tip to 0 implies that the finger is leaving
- * for both CrOS and Windows. A leaving finger would
- * never be re-considered by the OS.
- */
-
- /*
- * First, copy old values from the previous report.
- *
- * This is suggested on Windows although no
- * obvious problem has been noticed by not doing
- * so.
- */
- touch->finger[i] = touch_old->finger[i];
-
- /*
- * Leaving finger is not a palm by definition.
- *
- * Not clearing the confidence bit is essential
- * for tap-to-click to work on Windows.
- */
- touch->finger[i].confidence = 1;
-
- /* Leaving finger doesn't exist. */
- touch->finger[i].tip = 0;
-
- /*
- * Assume that the leaving finger is not hovering
- * either. We would inject one single fake hovering
- * finger later if necessary.
- */
- touch->finger[i].inrange = 0;
-
- contact_num++;
- }
-
- /* id is like slot in Linux MT-B so it is fixed every time. */
- touch->finger[i].id = i;
- }
-
- /* Check for hovering activity if there is no contact report. */
- if (!contact_num) {
- if (event->hover) {
- /* Put a fake finger at slot #0 if hover is detected. */
- touch->finger[0].inrange = 1;
- touch->finger[0].x = I2C_HID_TOUCHPAD_MAX_X / 2;
- touch->finger[0].y = I2C_HID_TOUCHPAD_MAX_Y / 2;
- contact_num++;
- } else if (!touch_old->finger[0].tip &&
- touch_old->finger[0].inrange) {
- /* Clear the fake hovering finger for host. */
- contact_num++;
- }
- }
-
- /* Fill in finger counts and the button state. */
- touch->count = I2C_HID_TOUCHPAD_MAX_FINGERS;
- touch->button = event->button;
-
- /*
- * Windows expects scan time to be in units of 100us. As Windows
- * measures the delta of scan times between the first and the current
- * report, we simply report the __hw_clock_source_read() value (which
- * is in resolution of 1us) divided by 100 as the scan time.
- */
- touch->timestamp = __hw_clock_source_read() / 100;
-
- /* Mouse report. */
- mouse->button1 = touch->button;
- if (touch->finger[0].tip == 1 && touch_old->finger[0].tip == 1) {
- /*
- * The relative X/Y movements in the mouse report are computed
- * based on the deltas of absolute X/Y positions between the
- * previous and current touch report. The computed deltas need
- * to be scaled for a smooth mouse movement.
- */
- mouse->x = (touch->finger[0].x - touch_old->finger[0].x) /
- I2C_HID_TOUCHPAD_MOUSE_SCALE_X;
- mouse->y = (touch->finger[0].y - touch_old->finger[0].y) /
- I2C_HID_TOUCHPAD_MOUSE_SCALE_Y;
- } else {
- mouse->x = 0;
- mouse->y = 0;
- }
-
- /* Swap buffer */
- report_active_index ^= 1;
-}
diff --git a/common/i2c_peripheral.c b/common/i2c_peripheral.c
deleted file mode 100644
index 20a4b4b0ae..0000000000
--- a/common/i2c_peripheral.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Copyright 2017 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.
- */
-
-/* I2C peripheral cross-platform code for Chrome EC */
-
-#include "host_command.h"
-#include "i2c.h"
-#include "util.h"
-
-enum ec_status i2c_get_protocol_info(struct host_cmd_handler_args *args)
-{
- struct ec_response_get_protocol_info *r = args->response;
-
- memset(r, 0, sizeof(*r));
- r->protocol_versions = BIT(3);
- r->max_request_packet_size = I2C_MAX_HOST_PACKET_SIZE;
- r->max_response_packet_size = I2C_MAX_HOST_PACKET_SIZE;
- r->flags = 0;
-
- args->response_size = sizeof(*r);
-
- return EC_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO,
- i2c_get_protocol_info,
- EC_VER_MASK(0));
diff --git a/common/i2c_trace.c b/common/i2c_trace.c
deleted file mode 100644
index 67b8864b22..0000000000
--- a/common/i2c_trace.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/* Copyright 2019 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.
- */
-
-#include "common.h"
-#include "console.h"
-#include "i2c.h"
-#include "stddef.h"
-#include "stdbool.h"
-#include "util.h"
-
-#define CPUTS(outstr) cputs(CC_I2C, outstr)
-#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args)
-
-struct i2c_trace_range {
- bool enabled;
- int port;
- int addr_lo; /* Inclusive */
- int addr_hi; /* Inclusive */
-};
-
-static struct i2c_trace_range trace_entries[8];
-
-void i2c_trace_notify(int port, uint16_t addr_flags,
- const uint8_t *out_data, size_t out_size,
- const uint8_t *in_data, size_t in_size)
-{
- size_t i;
- uint16_t addr = I2C_STRIP_FLAGS(addr_flags);
-
- for (i = 0; i < ARRAY_SIZE(trace_entries); i++)
- if (trace_entries[i].enabled
- && trace_entries[i].port == port
- && trace_entries[i].addr_lo <= addr
- && trace_entries[i].addr_hi >= addr)
- goto trace_enabled;
- return;
-
-trace_enabled:
- CPRINTF("i2c: %d:0x%X ", port, addr);
- if (out_size) {
- CPRINTF("wr ");
- for (i = 0; i < out_size; i++)
- CPRINTF("0x%02X ", out_data[i]);
- }
- if (in_size) {
- CPRINTF(" rd ");
- for (i = 0; i < in_size; i++)
- CPRINTF("0x%02X ", in_data[i]);
- }
- CPRINTF("\n");
-}
-
-static int command_i2ctrace_list(void)
-{
- size_t i;
- const struct i2c_port_t *i2c_port;
-
- ccprintf("id port address\n");
- ccprintf("-- ---- -------\n");
-
- for (i = 0; i < ARRAY_SIZE(trace_entries); i++) {
- if (trace_entries[i].enabled) {
- i2c_port = get_i2c_port(trace_entries[i].port);
- ccprintf("%-2zd %d %-8s 0x%X",
- i,
- trace_entries[i].port,
- i2c_port->name,
- trace_entries[i].addr_lo);
- if (trace_entries[i].addr_hi
- != trace_entries[i].addr_lo)
- ccprintf(" to 0x%X",
- trace_entries[i].addr_hi);
- ccprintf("\n");
- }
- }
-
- return EC_SUCCESS;
-}
-
-static int command_i2ctrace_disable(size_t id)
-{
- if (id >= ARRAY_SIZE(trace_entries))
- return EC_ERROR_PARAM2;
-
- trace_entries[id].enabled = 0;
- return EC_SUCCESS;
-}
-
-static int command_i2ctrace_enable(int port, int addr_lo,
- int addr_hi)
-{
- struct i2c_trace_range *t;
- struct i2c_trace_range *new_entry = NULL;
-
- if (!get_i2c_port(port))
- return EC_ERROR_PARAM2;
-
- if (addr_lo > addr_hi)
- return EC_ERROR_PARAM3;
-
- /*
- * Scan thru existing entries to see if there is one we can
- * extend instead of making a new entry
- */
- for (t = trace_entries;
- t < trace_entries + ARRAY_SIZE(trace_entries);
- t++) {
- if (t->enabled && t->port == port) {
- /* Subset of existing range, do nothing */
- if (t->addr_lo <= addr_lo &&
- t->addr_hi >= addr_hi)
- return EC_SUCCESS;
-
- /* Extends exising range on both directions, replace */
- if (t->addr_lo >= addr_lo &&
- t->addr_hi <= addr_hi) {
- t->enabled = 0;
- return command_i2ctrace_enable(
- port, addr_lo, addr_hi);
- }
-
- /* Extends existing range below */
- if (t->addr_lo - 1 <= addr_hi &&
- t->addr_hi >= addr_hi) {
- t->enabled = 0;
- return command_i2ctrace_enable(
- port,
- addr_lo,
- t->addr_hi);
- }
-
- /* Extends existing range above */
- if (t->addr_lo <= addr_lo &&
- t->addr_hi + 1 >= addr_lo) {
- t->enabled = 0;
- return command_i2ctrace_enable(
- port,
- t->addr_lo,
- addr_hi);
- }
- } else if (!t->enabled && !new_entry) {
- new_entry = t;
- }
- }
-
- /* We need to allocate a new entry */
- if (new_entry) {
- new_entry->enabled = 1;
- new_entry->port = port;
- new_entry->addr_lo = addr_lo;
- new_entry->addr_hi = addr_hi;
- return EC_SUCCESS;
- }
-
- ccprintf("No space to allocate new trace entry. Delete some first.\n");
- return EC_ERROR_MEMORY_ALLOCATION;
-}
-
-
-static int command_i2ctrace(int argc, char **argv)
-{
- int id_or_port;
- int address_low;
- int address_high;
- char *end;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- if (!strcasecmp(argv[1], "list") && argc == 2)
- return command_i2ctrace_list();
-
- if (argc < 3)
- return EC_ERROR_PARAM_COUNT;
-
- id_or_port = strtoi(argv[2], &end, 0);
- if (*end || id_or_port < 0)
- return EC_ERROR_PARAM2;
-
- if (!strcasecmp(argv[1], "disable") && argc == 3)
- return command_i2ctrace_disable(id_or_port);
-
- if (!strcasecmp(argv[1], "enable")) {
- address_low = strtoi(argv[3], &end, 0);
- if (*end || address_low < 0)
- return EC_ERROR_PARAM3;
-
- if (argc == 4) {
- address_high = address_low;
- } else if (argc == 5) {
- address_high = strtoi(argv[4], &end, 0);
- if (*end || address_high < 0)
- return EC_ERROR_PARAM4;
- } else {
- return EC_ERROR_PARAM_COUNT;
- }
-
- return command_i2ctrace_enable(
- id_or_port, address_low, address_high);
- }
-
- return EC_ERROR_PARAM1;
-}
-DECLARE_CONSOLE_COMMAND(i2ctrace,
- command_i2ctrace,
- "[list | disable <id> | enable <port> <address> | "
- "enable <port> <address-low> <address-high>]",
- "Trace I2C transactions");
diff --git a/common/i2c_wedge.c b/common/i2c_wedge.c
deleted file mode 100644
index 48bcac090c..0000000000
--- a/common/i2c_wedge.c
+++ /dev/null
@@ -1,341 +0,0 @@
-/* Copyright 2013 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.
- */
-
-/*
- * Define CONFIG_CMD_I2CWEDGE and I2C_PORT_HOST to enable the 'i2cwedge'
- * console command to allow us to bang the bus into a wedged state. For
- * example, include the following lines in board/pit/board.h to enable it on
- * pit:
- *
- * #define CONFIG_CMD_I2CWEDGE
- * #define I2C_PORT_HOST I2C_PORT_CONTROLLER
- *
- */
-
-#include "console.h"
-#include "gpio.h"
-#include "i2c.h"
-#include "system.h"
-#include "timer.h"
-#include "util.h"
-
-/*
- * The implementation is based on Wikipedia.
- */
-
-int i2c_bang_started;
-
-static void i2c_bang_delay(void)
-{
- udelay(5);
-}
-
-static void i2c_bang_start_cond(void)
-{
- /* Restart if needed */
- if (i2c_bang_started) {
- /* set SDA to 1 */
- i2c_raw_set_sda(I2C_PORT_HOST, 1);
- i2c_bang_delay();
-
- /* Clock stretching */
- i2c_raw_set_scl(I2C_PORT_HOST, 1);
- while (i2c_raw_get_scl(I2C_PORT_HOST) == 0)
- ; /* TODO(crosbug.com/p/26487): TIMEOUT */
-
- /* Repeated start setup time, minimum 4.7us */
- i2c_bang_delay();
- }
-
- i2c_raw_set_sda(I2C_PORT_HOST, 1);
- if (i2c_raw_get_sda(I2C_PORT_HOST) == 0)
- ; /* TODO(crosbug.com/p/26487): arbitration_lost */
-
- /* SCL is high, set SDA from 1 to 0. */
- i2c_raw_set_sda(I2C_PORT_HOST, 0);
- i2c_bang_delay();
- i2c_raw_set_scl(I2C_PORT_HOST, 0);
- i2c_bang_started = 1;
-
- ccputs("BITBANG: send start\n");
-}
-
-static void i2c_bang_stop_cond(void)
-{
- /* set SDA to 0 */
- i2c_raw_set_sda(I2C_PORT_HOST, 0);
- i2c_bang_delay();
-
- /* Clock stretching */
- i2c_raw_set_scl(I2C_PORT_HOST, 1);
- while (i2c_raw_get_scl(I2C_PORT_HOST) == 0)
- ; /* TODO(crosbug.com/p/26487): TIMEOUT */
-
- /* Stop bit setup time, minimum 4us */
- i2c_bang_delay();
-
- /* SCL is high, set SDA from 0 to 1 */
- i2c_raw_set_sda(I2C_PORT_HOST, 1);
- if (i2c_raw_get_sda(I2C_PORT_HOST) == 0)
- ; /* TODO(crosbug.com/p/26487): arbitration_lost */
-
- i2c_bang_delay();
-
- i2c_bang_started = 0;
- ccputs("BITBANG: send stop\n");
-}
-
-static void i2c_bang_out_bit(int bit)
-{
- if (bit)
- i2c_raw_set_sda(I2C_PORT_HOST, 1);
- else
- i2c_raw_set_sda(I2C_PORT_HOST, 0);
-
- i2c_bang_delay();
-
- /* Clock stretching */
- i2c_raw_set_scl(I2C_PORT_HOST, 1);
- while (i2c_raw_get_scl(I2C_PORT_HOST) == 0)
- ; /* TODO(crosbug.com/p/26487): TIMEOUT */
-
- /*
- * SCL is high, now data is valid
- * If SDA is high, check that nobody else is driving SDA
- */
- i2c_raw_set_sda(I2C_PORT_HOST, 1);
- if (bit && i2c_raw_get_sda(I2C_PORT_HOST) == 0)
- ; /* TODO(crosbug.com/p/26487): arbitration_lost */
-
- i2c_bang_delay();
- i2c_raw_set_scl(I2C_PORT_HOST, 0);
-}
-
-static int i2c_bang_in_bit(void)
-{
- int bit;
-
- /* Let the peripheral drive data */
- i2c_raw_set_sda(I2C_PORT_HOST, 1);
- i2c_bang_delay();
-
- /* Clock stretching */
- i2c_raw_set_scl(I2C_PORT_HOST, 1);
- while (i2c_raw_get_scl(I2C_PORT_HOST) == 0)
- ; /* TODO(crosbug.com/p/26487): TIMEOUT */
-
- /* SCL is high, now data is valid */
- bit = i2c_raw_get_sda(I2C_PORT_HOST);
- i2c_bang_delay();
- i2c_raw_set_scl(I2C_PORT_HOST, 0);
-
- return bit;
-}
-
-/* Write a byte to I2C bus. Return 0 if ack by the peripheral. */
-static int i2c_bang_out_byte(int send_start, int send_stop, unsigned char byte)
-{
- unsigned bit;
- int nack;
- int tmp = byte;
-
- if (send_start)
- i2c_bang_start_cond();
-
- for (bit = 0; bit < 8; bit++) {
- i2c_bang_out_bit((byte & 0x80) != 0);
- byte <<= 1;
- }
-
- nack = i2c_bang_in_bit();
-
- ccprintf(" write byte: %d ack/nack=%d\n", tmp, nack);
-
- if (send_stop)
- i2c_bang_stop_cond();
-
- return nack;
-}
-
-static unsigned char i2c_bang_in_byte(int ack, int send_stop)
-{
- unsigned char byte = 0;
- int i;
- for (i = 0; i < 8; ++i)
- byte = (byte << 1) | i2c_bang_in_bit();
- i2c_bang_out_bit(ack != 0);
- if (send_stop)
- i2c_bang_stop_cond();
- return byte;
-}
-
-static void i2c_bang_init(void)
-{
- i2c_bang_started = 0;
-
- i2c_raw_mode(I2C_PORT_HOST, 1);
-}
-
-static void i2c_bang_xfer(int addr, int reg)
-{
- int byte;
-
- i2c_bang_init();
-
- /* State a write command to 'addr' */
- i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, addr);
- /* Write 'reg' */
- i2c_bang_out_byte(0 /*start*/, 0 /*stop*/, reg);
-
- /* Start a read command */
- i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, addr | 1);
-
- /* Read two bytes */
- byte = i2c_bang_in_byte(0, 0); /* ack and no stop */
- ccprintf(" read byte: %d\n", byte);
- byte = i2c_bang_in_byte(1, 1); /* nack and stop */
- ccprintf(" read byte: %d\n", byte);
-}
-
-static void i2c_bang_wedge_write(int addr, int byte, int bit_count,
- int reboot)
-{
- int i;
-
- i2c_bang_init();
-
- /* State a write command to 'addr' */
- i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, addr);
- /* Send a few bits and stop */
- for (i = 0; i < bit_count; ++i) {
- i2c_bang_out_bit((byte & 0x80) != 0);
- byte <<= 1;
- }
- ccprintf(" wedged write after %d bits\n", bit_count);
-
- if (reboot)
- system_reset(0);
-}
-
-static void i2c_bang_wedge_read(int addr, int reg, int bit_count,
- int reboot)
-{
- int i;
-
- i2c_bang_init();
-
- /* State a write command to 'addr' */
- i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, addr);
- /* Write 'reg' */
- i2c_bang_out_byte(0 /*start*/, 0 /*stop*/, reg);
-
- /* Start a read command */
- i2c_bang_out_byte(1 /*start*/, 0 /*stop*/, addr | 1);
-
- /* Read bit_count bits and stop */
- for (i = 0; i < bit_count; ++i)
- i2c_bang_in_bit();
-
- ccprintf(" wedged read after %d bits\n", bit_count);
-
- if (reboot)
- system_reset(0);
-}
-
-#define WEDGE_WRITE 1
-#define WEDGE_READ 2
-#define WEDGE_REBOOT 4
-
-static int command_i2c_wedge(int argc, char **argv)
-{
- int addr, reg, wedge_flag = 0, wedge_bit_count = -1;
- char *e;
- enum gpio_signal tmp;
-
- /* Verify that the I2C_PORT_HOST has SDA and SCL pins defined. */
- if (get_sda_from_i2c_port(I2C_PORT_HOST, &tmp) != EC_SUCCESS ||
- get_scl_from_i2c_port(I2C_PORT_HOST, &tmp) != EC_SUCCESS) {
- ccprintf("Cannot wedge bus because no SCL and SDA pins are"
- "defined for this port. Check i2c_ports[].\n");
- return EC_SUCCESS;
- }
-
- if (argc < 3) {
- ccputs("Usage: i2cwedge addr out_byte "
- "[wedge_flag [wedge_bit_count]]\n");
- ccputs(" wedge_flag - (1: wedge out; 2: wedge in;"
- " 5: wedge out+reboot; 6: wedge in+reboot)]\n");
- ccputs(" wedge_bit_count - 0 to 8\n");
- return EC_ERROR_UNKNOWN;
- }
-
- addr = strtoi(argv[1], &e, 0);
- if (*e) {
- ccprintf("Invalid addr %s\n", argv[1]);
- return EC_ERROR_INVAL;
- }
- reg = strtoi(argv[2], &e, 0);
- if (*e) {
- ccprintf("Invalid out_byte %s\n", argv[2]);
- return EC_ERROR_INVAL;
- }
- if (argc > 3) {
- wedge_flag = strtoi(argv[3], &e, 0);
- if (*e) {
- ccprintf("Invalid wedge_flag %s\n", argv[3]);
- return EC_ERROR_INVAL;
- }
- }
- if (argc > 4) {
- wedge_bit_count = strtoi(argv[4], &e, 0);
- if (*e || wedge_bit_count < 0 || wedge_bit_count > 8) {
- ccprintf("Invalid wedge_bit_count %s.\n", argv[4]);
- return EC_ERROR_INVAL;
- }
- }
-
- i2c_lock(I2C_PORT_HOST, 1);
-
- if (wedge_flag & WEDGE_WRITE) {
- if (wedge_bit_count < 0)
- wedge_bit_count = 8;
- i2c_bang_wedge_write(addr, reg, wedge_bit_count,
- (wedge_flag & WEDGE_REBOOT));
- } else if (wedge_flag & WEDGE_READ) {
- if (wedge_bit_count < 0)
- wedge_bit_count = 2;
- i2c_bang_wedge_read(addr, reg, wedge_bit_count,
- (wedge_flag & WEDGE_REBOOT));
- } else {
- i2c_bang_xfer(addr, reg);
- }
-
- /* Put it back into normal mode */
- i2c_raw_mode(I2C_PORT_HOST, 0);
-
- i2c_lock(I2C_PORT_HOST, 0);
-
- if (wedge_flag & (WEDGE_WRITE | WEDGE_READ))
- ccprintf("I2C bus %d is now wedged. Enjoy.\n", I2C_PORT_HOST);
- else
- ccprintf("Bit bang xfer complete.\n");
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(i2cwedge, command_i2c_wedge,
- "i2cwedge addr out_byte "
- "[wedge_flag [wedge_bit_count]]",
- "Wedge host I2C bus");
-
-static int command_i2c_unwedge(int argc, char **argv)
-{
- i2c_unwedge(I2C_PORT_HOST);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(i2cunwedge, command_i2c_unwedge,
- "",
- "Unwedge host I2C bus");
-
diff --git a/common/inductive_charging.c b/common/inductive_charging.c
deleted file mode 100644
index 793f535afe..0000000000
--- a/common/inductive_charging.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/* Copyright 2014 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.
- */
-
-/* Inductive charging control */
-
-#include "common.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "inductive_charging.h"
-#include "lid_switch.h"
-#include "timer.h"
-
-/*
- * The inductive charger is controlled with two signals:
- * - BASE_CHG_VDD_EN controls whether the charger is powered.
- * - CHARGE_EN controls whether to enable charging.
- * Charging status is reported via CHARGE_DONE, but in a tricky way:
- * - It's 0 if:
- * + The charger is unpowered. (i.e. BASE_CHG_VDD_EN = 0)
- * + Or charging is disabled. (i.e. CHARGE_EN = 0)
- * + Or the charging current is small enough.
- * - Otherwise, it's 1.
- */
-
-/* Whether we want to process interrupts on CHARGE_DONE or not. */
-static int monitor_charge_done;
-
-/*
- * Start monitoring CHARGE_DONE and fires the interrupt once so that
- * we react to the current value.
- */
-static void inductive_charging_monitor_charge(void)
-{
- monitor_charge_done = 1;
- inductive_charging_interrupt(GPIO_CHARGE_DONE);
-}
-DECLARE_DEFERRED(inductive_charging_monitor_charge);
-
-void inductive_charging_interrupt(enum gpio_signal signal)
-{
- int charger_enabled = gpio_get_level(GPIO_BASE_CHG_VDD_EN);
- int charge_done = gpio_get_level(GPIO_CHARGE_DONE);
- static int charge_already_done;
-
- if (!monitor_charge_done && signal == GPIO_CHARGE_DONE)
- return;
-
- if (signal == GPIO_LID_OPEN) {
- /* The lid has been opened. Clear all states. */
- charge_done = 0;
- charge_already_done = 0;
- monitor_charge_done = 0;
- } else if (signal == GPIO_CHARGE_DONE) {
- /*
- * Once we see CHARGE_DONE=1, we ignore any change on
- * CHARGE_DONE until the next time the lid is opened.
- */
- if (charge_done == 1)
- charge_already_done = 1;
- else if (charge_already_done)
- return;
- }
-
- if (!charger_enabled || charge_done) {
- gpio_set_level(GPIO_CHARGE_EN, 0);
- } else {
- gpio_set_level(GPIO_CHARGE_EN, 1);
- /*
- * When the charging is just enabled, there might be a
- * blip on CHARGE_DONE. Wait for a second before we start
- * looking at CHARGE_DONE.
- */
- if (!monitor_charge_done)
- hook_call_deferred(
- &inductive_charging_monitor_charge_data,
- SECOND);
- }
-}
-
-static void inductive_charging_deferred_update(void)
-{
- int lid_open = lid_is_open();
- gpio_set_level(GPIO_BASE_CHG_VDD_EN, !lid_open);
- inductive_charging_interrupt(GPIO_LID_OPEN);
-}
-DECLARE_DEFERRED(inductive_charging_deferred_update);
-
-static void inductive_charging_lid_update(void)
-{
- /*
- * When the lid close signal changes, the coils might still be
- * unaligned. Delay here to give the coils time to align before
- * we try to clear CHARGE_DONE.
- */
- hook_call_deferred(&inductive_charging_deferred_update_data,
- 5 * SECOND);
-}
-DECLARE_HOOK(HOOK_LID_CHANGE, inductive_charging_lid_update, HOOK_PRIO_DEFAULT);
-
-static void inductive_charging_init(void)
-{
- gpio_enable_interrupt(GPIO_CHARGE_DONE);
- inductive_charging_lid_update();
-}
-DECLARE_HOOK(HOOK_INIT, inductive_charging_init, HOOK_PRIO_DEFAULT);
diff --git a/common/init_rom.c b/common/init_rom.c
deleted file mode 100644
index 320849c008..0000000000
--- a/common/init_rom.c
+++ /dev/null
@@ -1,69 +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.
- */
-
-/* Init ROM module for Chrome EC */
-
-#include "builtin/assert.h"
-#include "common.h"
-#include "init_rom.h"
-#include "flash.h"
-#include "stdbool.h"
-#include "stddef.h"
-
-const void *init_rom_map(const void *addr, int size)
-{
- const char *src;
- uintptr_t offset;
-
- /*
- * When CONFIG_CHIP_INIT_ROM_REGION isn't enabled, .init_rom objects
- * are linked into the .rodata section and directly addressable.
- * Return the caller's pointer.
- */
- if (!IS_ENABLED(CONFIG_CHIP_INIT_ROM_REGION))
- return addr;
-
- /*
- * When flash isn't memory mapped, caller's must use init_rom_copy()
- * to copy .init_rom data into RAM.
- */
- if (!IS_ENABLED(CONFIG_MAPPED_STORAGE))
- return NULL;
-
- /*
- * Safe pointer conversion - needed for host tests which can have
- * 64-bit pointers.
- */
- offset = (uintptr_t)addr;
-
- ASSERT(offset <= __INT_MAX__);
-
- /*
- * Convert flash offset to memory mapped address
- */
- if (crec_flash_dataptr((int)offset, size, 1, &src) < 0)
- return NULL;
-
- /* Once the flash offset is validated, lock the flash for the caller */
- crec_flash_lock_mapped_storage(1);
-
- return src;
-}
-
-/*
- * The addr and size parameters are provided for forward compatibility if
- * the flash API is extended to support locking less than the entire flash.
- */
-void init_rom_unmap(const void *addr, int size)
-{
- if (IS_ENABLED(CONFIG_CHIP_INIT_ROM_REGION))
- crec_flash_lock_mapped_storage(0);
-}
-
-int init_rom_copy(int offset, int size, char *data)
-{
- return crec_flash_read(offset, size, data);
-}
-
diff --git a/common/ioexpander.c b/common/ioexpander.c
deleted file mode 100644
index ccf3cc7c4a..0000000000
--- a/common/ioexpander.c
+++ /dev/null
@@ -1,338 +0,0 @@
-/* Copyright 2019 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.
- */
-
-/* IO Expander Controller Common Code */
-
-#include "console.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "ioexpander.h"
-#include "system.h"
-#include "util.h"
-
-#define CPRINTF(format, args...) cprintf(CC_GPIO, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_GPIO, format, ## args)
-
-static uint8_t last_val[(IOEX_COUNT + 7) / 8];
-
-static int last_val_changed(enum ioex_signal signal, int v)
-{
- const int i = signal - IOEX_SIGNAL_START;
-
- ASSERT(signal_is_ioex(signal));
-
- if (v && !(last_val[i / 8] & (BIT(i % 8)))) {
- last_val[i / 8] |= BIT(i % 8);
- return 1;
- } else if (!v && last_val[i / 8] & (BIT(i % 8))) {
- last_val[i / 8] &= ~(BIT(i % 8));
- return 1;
- } else {
- return 0;
- }
-}
-
-int signal_is_ioex(int signal)
-{
- return ((signal >= IOEX_SIGNAL_START) && (signal < IOEX_SIGNAL_END));
-}
-
-static const struct ioex_info *ioex_get_signal_info(enum ioex_signal signal)
-{
- const struct ioex_info *g;
-
- ASSERT(signal_is_ioex(signal));
-
- g = ioex_list + signal - IOEX_SIGNAL_START;
-
- if (ioex_config[g->ioex].flags & IOEX_FLAGS_DISABLED) {
- CPRINTS("ioex %s disabled", g->name);
- return NULL;
- }
-
- return g;
-}
-
-static int ioex_is_valid_interrupt_signal(enum ioex_signal signal)
-{
- const struct ioexpander_drv *drv;
- const struct ioex_info *g = ioex_get_signal_info(signal);
-
- if (g == NULL)
- return EC_ERROR_BUSY;
-
- /* Fail if no interrupt handler */
- if (signal - IOEX_SIGNAL_START >= ioex_ih_count)
- return EC_ERROR_PARAM1;
-
- drv = ioex_config[g->ioex].drv;
- /*
- * Not every IOEX chip can support interrupt, check it before enabling
- * the interrupt function
- */
- if (drv->enable_interrupt == NULL) {
- CPRINTS("IOEX chip port %d doesn't support INT", g->ioex);
- return EC_ERROR_UNIMPLEMENTED;
- }
-
- return EC_SUCCESS;
-}
-
-int ioex_enable_interrupt(enum ioex_signal signal)
-{
- int rv;
- const struct ioex_info *g = ioex_get_signal_info(signal);
- const struct ioexpander_drv *drv;
-
- rv = ioex_is_valid_interrupt_signal(signal);
- if (rv != EC_SUCCESS)
- return rv;
-
- drv = ioex_config[g->ioex].drv;
- return drv->enable_interrupt(g->ioex, g->port, g->mask, 1);
-}
-
-int ioex_disable_interrupt(enum ioex_signal signal)
-{
- int rv;
- const struct ioexpander_drv *drv;
- const struct ioex_info *g = ioex_get_signal_info(signal);
-
- rv = ioex_is_valid_interrupt_signal(signal);
- if (rv != EC_SUCCESS)
- return rv;
-
- drv = ioex_config[g->ioex].drv;
- return drv->enable_interrupt(g->ioex, g->port, g->mask, 0);
-}
-
-int ioex_get_flags(enum ioex_signal signal, int *flags)
-{
- const struct ioex_info *g = ioex_get_signal_info(signal);
-
- if (g == NULL)
- return EC_ERROR_BUSY;
-
- return ioex_config[g->ioex].drv->get_flags_by_mask(g->ioex,
- g->port, g->mask, flags);
-}
-
-int ioex_set_flags(enum ioex_signal signal, int flags)
-{
- const struct ioex_info *g = ioex_get_signal_info(signal);
-
- if (g == NULL)
- return EC_ERROR_BUSY;
-
- return ioex_config[g->ioex].drv->set_flags_by_mask(g->ioex,
- g->port, g->mask, flags);
-}
-
-int ioex_get_level(enum ioex_signal signal, int *val)
-{
- const struct ioex_info *g = ioex_get_signal_info(signal);
-
- if (g == NULL)
- return EC_ERROR_BUSY;
-
- return ioex_config[g->ioex].drv->get_level(g->ioex, g->port,
- g->mask, val);
-}
-
-int ioex_set_level(enum ioex_signal signal, int value)
-{
- const struct ioex_info *g = ioex_get_signal_info(signal);
-
- if (g == NULL)
- return EC_ERROR_BUSY;
-
- return ioex_config[g->ioex].drv->set_level(g->ioex, g->port,
- g->mask, value);
-}
-
-#ifdef CONFIG_IO_EXPANDER_SUPPORT_GET_PORT
-int ioex_get_port(int ioex, int port, int *val)
-{
- if (ioex_config[ioex].drv->get_port == NULL)
- return EC_ERROR_UNIMPLEMENTED;
-
- return ioex_config[ioex].drv->get_port(ioex, port, val);
-}
-#endif
-
-int ioex_init(int ioex)
-{
- const struct ioex_info *g = ioex_list;
- const struct ioexpander_drv *drv = ioex_config[ioex].drv;
- int rv;
- int i;
-
- if (ioex_config[ioex].flags & IOEX_FLAGS_DISABLED)
- return EC_ERROR_BUSY;
-
- if (drv->init != NULL) {
- rv = drv->init(ioex);
- if (rv != EC_SUCCESS)
- return rv;
- }
-
- /*
- * Set all IO expander GPIOs to default flags according to the setting
- * in gpio.inc
- */
- for (i = 0; i < IOEX_COUNT; i++, g++) {
- int flags = g->flags;
-
- if (g->ioex == ioex && g->mask && !(flags & GPIO_DEFAULT)) {
- /* Late-sysJump should not set the output levels */
- if (system_jumped_late())
- flags &= ~(GPIO_LOW | GPIO_HIGH);
-
- drv->set_flags_by_mask(g->ioex, g->port,
- g->mask, flags);
- }
- }
-
- return EC_SUCCESS;
-}
-
-static void ioex_init_default(void)
-{
- int i;
-
- for (i = 0; i < CONFIG_IO_EXPANDER_PORT_COUNT; i++)
- ioex_init(i);
-}
-DECLARE_HOOK(HOOK_INIT, ioex_init_default, HOOK_PRIO_INIT_I2C + 1);
-
-const char *ioex_get_name(enum ioex_signal signal)
-{
- const struct ioex_info *g = ioex_list + signal - IOEX_SIGNAL_START;
-
- return g->name;
-}
-
-static void print_ioex_info(enum ioex_signal signal)
-{
- int changed, v, val;
- int flags = 0;
- const struct ioex_info *g = ioex_list + signal - IOEX_SIGNAL_START;
-
- if (ioex_config[g->ioex].flags & IOEX_FLAGS_DISABLED) {
- ccprintf(" DISABLED %s\n", ioex_get_name(signal));
- return;
- }
-
-
- v = ioex_get_level(signal, &val);
- if (v) {
- ccprintf("Fail to get %s level\n", ioex_get_name(signal));
- return;
- }
- v = ioex_get_flags(signal, &flags);
- if (v) {
- ccprintf("Fail to get %s flags\n", ioex_get_name(signal));
- return;
- }
-
- changed = last_val_changed(signal, val);
-
- ccprintf(" %d%c %s%s%s%s%s%s\n", val,
- (changed ? '*' : ' '),
- (flags & GPIO_INPUT ? "I " : ""),
- (flags & GPIO_OUTPUT ? "O " : ""),
- (flags & GPIO_LOW ? "L " : ""),
- (flags & GPIO_HIGH ? "H " : ""),
- (flags & GPIO_OPEN_DRAIN ? "ODR " : ""),
- ioex_get_name(signal));
-
- /* Flush console to avoid truncating output */
- cflush();
-}
-
-static int ioex_get_default_flags(enum ioex_signal signal)
-{
- const struct ioex_info *g = ioex_get_signal_info(signal);
-
- if (g == NULL)
- return 0;
-
- return g->flags;
-}
-
-/* IO expander commands */
-static enum ioex_signal find_ioex_by_name(const char *name)
-{
- enum ioex_signal signal;
-
- if (!name)
- return IOEX_SIGNAL_END;
-
- for (signal = IOEX_SIGNAL_START; signal < IOEX_SIGNAL_END; signal++) {
- if (!strcasecmp(name, ioex_get_name(signal)))
- return signal;
- }
-
- return IOEX_SIGNAL_END;
-}
-
-static enum ec_error_list ioex_set(const char *name, int value)
-{
- enum ioex_signal signal = find_ioex_by_name(name);
-
- if (!signal_is_ioex(signal))
- return EC_ERROR_INVAL;
-
- if (!(ioex_get_default_flags(signal) & GPIO_OUTPUT))
- return EC_ERROR_INVAL;
-
- return ioex_set_level(signal, value);
-}
-
-static int command_ioex_set(int argc, char **argv)
-{
- char *e;
- int v;
-
- if (argc < 3)
- return EC_ERROR_PARAM_COUNT;
-
- v = strtoi(argv[2], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2;
-
- if (ioex_set(argv[1], v) != EC_SUCCESS)
- return EC_ERROR_PARAM1;
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(ioexset, command_ioex_set,
- "name <0 | 1>",
- "Set level of a IO expander IO");
-
-static int command_ioex_get(int argc, char **argv)
-{
- enum ioex_signal signal;
-
- /* If a signal is specified, print only that one */
- if (argc == 2) {
- signal = find_ioex_by_name(argv[1]);
- if (!signal_is_ioex(signal))
- return EC_ERROR_PARAM1;
- print_ioex_info(signal);
-
- return EC_SUCCESS;
- }
-
- /* Otherwise print them all */
- for (signal = IOEX_SIGNAL_START; signal < IOEX_SIGNAL_END; signal++)
- print_ioex_info(signal);
-
- return EC_SUCCESS;
-}
-DECLARE_SAFE_CONSOLE_COMMAND(ioexget, command_ioex_get,
- "[name]",
- "Read level of IO expander pin(s)");
-
diff --git a/common/keyboard_8042.c b/common/keyboard_8042.c
deleted file mode 100644
index 699eaa6687..0000000000
--- a/common/keyboard_8042.c
+++ /dev/null
@@ -1,1328 +0,0 @@
-/* Copyright 2013 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.
- *
- * 8042 keyboard protocol
- */
-
-#include "chipset.h"
-#include "button.h"
-#include "common.h"
-#include "console.h"
-#include "device_event.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "i8042_protocol.h"
-#include "keyboard_8042_sharedlib.h"
-#include "keyboard_config.h"
-#include "keyboard_protocol.h"
-#include "lightbar.h"
-#include "lpc.h"
-#include "power_button.h"
-#include "queue.h"
-#include "shared_mem.h"
-#include "system.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_KEYBOARD, outstr)
-#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args)
-
-#ifdef CONFIG_KEYBOARD_DEBUG
-#define CPUTS5(outstr) cputs(CC_KEYBOARD, outstr)
-#define CPRINTS5(format, args...) cprints(CC_KEYBOARD, format, ## args)
-#else
-#define CPUTS5(outstr)
-#define CPRINTS5(format, args...)
-#endif
-
-/*
- * This command needs malloc to work. Could we use this instead?
- *
- * #define CMD_KEYBOARD_LOG IS_ENABLED(CONFIG_MALLOC)
- */
-#ifdef CONFIG_MALLOC
-#define CMD_KEYBOARD_LOG 1
-#else
-#define CMD_KEYBOARD_LOG 0
-#endif
-
-static enum {
- STATE_NORMAL = 0,
- STATE_SCANCODE,
- STATE_SETLEDS,
- STATE_EX_SETLEDS_1, /* Expect 2-byte parameter */
- STATE_EX_SETLEDS_2,
- STATE_WRITE_CMD_BYTE,
- STATE_WRITE_OUTPUT_PORT,
- STATE_ECHO_MOUSE,
- STATE_SETREP,
- STATE_SEND_TO_MOUSE,
-} data_port_state = STATE_NORMAL;
-
-enum scancode_set_list {
- SCANCODE_GET_SET = 0,
- SCANCODE_SET_1,
- SCANCODE_SET_2,
- SCANCODE_SET_3,
- SCANCODE_MAX = SCANCODE_SET_3,
-};
-
-#define MAX_SCAN_CODE_LEN 4
-
-/* Number of bytes host can get behind before we start generating extra IRQs */
-#define KB_TO_HOST_RETRIES 3
-
-/*
- * Mutex to control write access to the to-host buffer head. Don't need to
- * mutex the tail because reads are only done in one place.
- */
-static mutex_t to_host_mutex;
-
-/* Queue command/data to the host */
-enum {
- CHAN_KBD = 0,
- CHAN_AUX,
-};
-struct data_byte {
- uint8_t chan;
- uint8_t byte;
-};
-
-static struct queue const to_host = QUEUE_NULL(16, struct data_byte);
-
-/* Queue command/data from the host */
-enum {
- HOST_COMMAND = 0,
- HOST_DATA,
-};
-struct host_byte {
- uint8_t type;
- uint8_t byte;
-};
-
-/*
- * The buffer for i8042 command from host. So far the largest command
- * we see from kernel is:
- *
- * d1 -> i8042 (command) # enable A20 in i8042_platform_init() of
- * df -> i8042 (parameter) # serio/i8042-x86ia64io.h file.
- * ff -> i8042 (command)
- * 20 -> i8042 (command) # read CTR
- *
- * Hence, 5 (actually 4 plus one spare) is large enough, but use 8 for safety.
- */
-static struct queue const from_host = QUEUE_NULL(8, struct host_byte);
-
-/* Queue aux data to the host from interrupt context. */
-static struct queue const aux_to_host_queue = QUEUE_NULL(16, uint8_t);
-
-static int i8042_keyboard_irq_enabled;
-static int i8042_aux_irq_enabled;
-
-/* i8042 global settings */
-static int keyboard_enabled; /* default the keyboard is disabled. */
-static int aux_chan_enabled; /* default the mouse is disabled. */
-static int keystroke_enabled; /* output keystrokes */
-static uint8_t resend_command[MAX_SCAN_CODE_LEN];
-static uint8_t resend_command_len;
-static uint8_t controller_ram_address;
-static uint8_t controller_ram[0x20] = {
- /* the so called "command byte" */
- I8042_XLATE | I8042_AUX_DIS | I8042_KBD_DIS,
- /* 0x01 - 0x1f are controller RAM */
-};
-static uint8_t A20_status;
-
-/*
- * Scancode settings
- */
-static enum scancode_set_list scancode_set = SCANCODE_SET_2;
-
-/*
- * Typematic delay, rate and counter variables.
- *
- * 7 6 5 4 3 2 1 0
- * +-----+-----+-----+-----+-----+-----+-----+-----+
- * |un- | delay | B | D |
- * | used| 0 1 | 0 1 | 0 1 1 |
- * +-----+-----+-----+-----+-----+-----+-----+-----+
- * Formula:
- * the inter-char delay = (2 ** B) * (D + 8) / 240 (sec)
- * Default: 500ms delay, 10.9 chars/sec.
- */
-#define DEFAULT_TYPEMATIC_VALUE (BIT(5) | BIT(3) | (3 << 0))
-static uint8_t typematic_value_from_host;
-static int typematic_first_delay;
-static int typematic_inter_delay;
-static int typematic_len; /* length of typematic_scan_code */
-static uint8_t typematic_scan_code[MAX_SCAN_CODE_LEN];
-static timestamp_t typematic_deadline;
-
-#define KB_SYSJUMP_TAG 0x4b42 /* "KB" */
-#define KB_HOOK_VERSION 2
-/* the previous keyboard state before reboot_ec. */
-struct kb_state {
- uint8_t codeset;
- uint8_t ctlram;
- uint8_t keystroke_enabled;
-};
-
-/*****************************************************************************/
-/* Keyboard event log */
-
-/* Log the traffic between EC and host -- for debug only */
-#define MAX_KBLOG 512 /* Max events in keyboard log */
-
-struct kblog_t {
- /*
- * Type:
- *
- * s = byte enqueued to send to host
- * a = aux byte enqueued to send to host
- * t = to-host queue tail pointer before type='s' bytes enqueued
- *
- * d = data byte from host
- * c = command byte from host
- *
- * k = to-host queue head pointer before byte dequeued
- * K = byte actually sent to host via LPC
- * A = byte actually sent to host via LPC as AUX
- *
- * x = to_host queue was cleared
- *
- * The to-host head and tail pointers are logged pre-wrapping to the
- * queue size. This means that they continually increment as units
- * are dequeued and enqueued respectively. Since only the bottom
- * byte of the value is logged they will wrap every 256 units.
- */
- uint8_t type;
- uint8_t byte;
-};
-
-static struct kblog_t *kblog_buf; /* Log buffer; NULL if not logging */
-static int kblog_len; /* Current log length */
-
-/**
- * Add event to keyboard log.
- */
-static void kblog_put(char type, uint8_t byte)
-{
- if (kblog_buf && kblog_len < MAX_KBLOG) {
- kblog_buf[kblog_len].type = type;
- kblog_buf[kblog_len].byte = byte;
- kblog_len++;
- }
-}
-
-/*****************************************************************************/
-
-void keyboard_host_write(int data, int is_cmd)
-{
- struct host_byte h;
-
- h.type = is_cmd ? HOST_COMMAND : HOST_DATA;
- h.byte = data;
- queue_add_unit(&from_host, &h);
- task_wake(TASK_ID_KEYPROTO);
-}
-
-/**
- * Enable keyboard IRQ generation.
- *
- * @param enable Enable (!=0) or disable (0) IRQ generation.
- */
-static void keyboard_enable_irq(int enable)
-{
- CPRINTS("KB IRQ %s", enable ? "enable" : "disable");
-
- i8042_keyboard_irq_enabled = enable;
- if (enable)
- lpc_keyboard_resume_irq();
-}
-
-/**
- * Enable mouse IRQ generation.
- *
- * @param enable Enable (!=0) or disable (0) IRQ generation.
- */
-static void aux_enable_irq(int enable)
-{
- CPRINTS("AUX IRQ %s", enable ? "enable" : "disable");
-
- i8042_aux_irq_enabled = enable;
-}
-
-/**
- * Send a scan code to the host.
- *
- * The EC lib will push the scan code bytes to host via port 0x60 and assert
- * the IBF flag to trigger an interrupt. The EC lib must queue them if the
- * host cannot read the previous byte away in time.
- *
- * @param len Number of bytes to send to the host
- * @param to_host Data to send
- * @param chan Channel to send data on
- */
-static void i8042_send_to_host(int len, const uint8_t *bytes,
- uint8_t chan)
-{
- int i;
- struct data_byte data;
-
- /* Enqueue output data if there's space */
- mutex_lock(&to_host_mutex);
-
- for (i = 0; i < len; i++)
- kblog_put(chan == CHAN_AUX ? 'a' : 's', bytes[i]);
-
- if (queue_space(&to_host) >= len) {
- kblog_put('t', to_host.state->tail);
- for (i = 0; i < len; i++) {
- data.chan = chan;
- data.byte = bytes[i];
- queue_add_unit(&to_host, &data);
- }
- }
- mutex_unlock(&to_host_mutex);
-
- /* Wake up the task to move from queue to host */
- task_wake(TASK_ID_KEYPROTO);
-}
-
-/* Change to set 1 if the I8042_XLATE flag is set. */
-static enum scancode_set_list acting_code_set(enum scancode_set_list set)
-{
- /* Always generate set 1 if keyboard translation is enabled */
- if (controller_ram[0] & I8042_XLATE)
- return SCANCODE_SET_1;
-
- return set;
-}
-
-static int is_supported_code_set(enum scancode_set_list set)
-{
- return (set == SCANCODE_SET_1 || set == SCANCODE_SET_2);
-}
-
-/**
- * Return the make or break code bytes for the active scancode set.
- *
- * @param make_code The make code to generate the make or break code from
- * @param pressed Whether the key or button was pressed
- * @param code_set The scancode set being used
- * @param scan_code An array of bytes to store the make or break code in
- * @param len The number of valid bytes to send in scan_code
- */
-static void scancode_bytes(uint16_t make_code, int8_t pressed,
- enum scancode_set_list code_set, uint8_t *scan_code,
- int32_t *len)
-{
- *len = 0;
-
- /* Output the make code (from table) */
- if (make_code >= 0x0100) {
- scan_code[(*len)++] = make_code >> 8;
- make_code &= 0xff;
- }
-
- switch (code_set) {
- case SCANCODE_SET_1:
- make_code = scancode_translate_set2_to_1(make_code);
- scan_code[(*len)++] = pressed ? make_code : (make_code | 0x80);
- break;
-
- case SCANCODE_SET_2:
- if (pressed) {
- scan_code[(*len)++] = make_code;
- } else {
- scan_code[(*len)++] = 0xf0;
- scan_code[(*len)++] = make_code;
- }
- break;
- default:
- break;
- }
-}
-
-static enum ec_error_list matrix_callback(int8_t row, int8_t col,
- int8_t pressed,
- enum scancode_set_list code_set,
- uint8_t *scan_code, int32_t *len)
-{
- uint16_t make_code;
-
- ASSERT(scan_code);
- ASSERT(len);
-
- if (row >= KEYBOARD_ROWS || col >= keyboard_cols)
- return EC_ERROR_INVAL;
-
- make_code = get_scancode_set2(row, col);
-
-#ifdef CONFIG_KEYBOARD_SCANCODE_CALLBACK
- {
- enum ec_error_list r = keyboard_scancode_callback(
- &make_code, pressed);
- if (r != EC_SUCCESS)
- return r;
- }
-#endif
-
- code_set = acting_code_set(code_set);
- if (!is_supported_code_set(code_set)) {
- CPRINTS("KB scancode set %d unsupported", code_set);
- return EC_ERROR_UNIMPLEMENTED;
- }
-
- if (!make_code) {
- CPRINTS("KB scancode %d:%d missing", row, col);
- return EC_ERROR_UNIMPLEMENTED;
- }
-
- scancode_bytes(make_code, pressed, code_set, scan_code, len);
- return EC_SUCCESS;
-}
-
-/**
- * Set typematic delays based on host data byte.
- */
-static void set_typematic_delays(uint8_t data)
-{
- typematic_value_from_host = data;
- typematic_first_delay = MSEC *
- (((typematic_value_from_host & 0x60) >> 5) + 1) * 250;
- typematic_inter_delay = SECOND *
- (1 << ((typematic_value_from_host & 0x18) >> 3)) *
- ((typematic_value_from_host & 0x7) + 8) / 240;
-}
-
-static void reset_rate_and_delay(void)
-{
- set_typematic_delays(DEFAULT_TYPEMATIC_VALUE);
-}
-
-void keyboard_clear_buffer(void)
-{
- CPRINTS("KB Clear Buffer");
- mutex_lock(&to_host_mutex);
- kblog_put('x', queue_count(&to_host));
- queue_init(&to_host);
- mutex_unlock(&to_host_mutex);
- lpc_keyboard_clear_buffer();
-}
-
-static void keyboard_wakeup(void)
-{
- host_set_single_event(EC_HOST_EVENT_KEY_PRESSED);
-}
-
-static void set_typematic_key(const uint8_t *scan_code, int32_t len)
-{
- typematic_deadline.val = get_time().val + typematic_first_delay;
- memcpy(typematic_scan_code, scan_code, len);
- typematic_len = len;
-}
-
-void clear_typematic_key(void)
-{
- typematic_len = 0;
-}
-
-void keyboard_state_changed(int row, int col, int is_pressed)
-{
- uint8_t scan_code[MAX_SCAN_CODE_LEN];
- int32_t len = 0;
- enum ec_error_list ret;
-
-#ifdef CONFIG_KEYBOARD_DEBUG
- char mylabel = get_keycap_label(row, col);
-
- if (mylabel & KEYCAP_LONG_LABEL_BIT)
- CPRINTS("KB (%d,%d)=%d %s", row, col, is_pressed,
- get_keycap_long_label(mylabel & KEYCAP_LONG_LABEL_INDEX_BITMASK));
- else
- CPRINTS("KB (%d,%d)=%d %c", row, col, is_pressed, mylabel);
-#endif
-
- ret = matrix_callback(row, col, is_pressed, scancode_set, scan_code,
- &len);
- if (ret == EC_SUCCESS) {
- ASSERT(len > 0);
- if (keystroke_enabled)
- i8042_send_to_host(len, scan_code, CHAN_KBD);
- }
-
- if (is_pressed) {
- keyboard_wakeup();
- set_typematic_key(scan_code, len);
- task_wake(TASK_ID_KEYPROTO);
- } else {
- clear_typematic_key();
- }
-}
-
-static void keystroke_enable(int enable)
-{
- if (!keystroke_enabled && enable)
- CPRINTS("KS enable");
- else if (keystroke_enabled && !enable)
- CPRINTS("KS disable");
-
- keystroke_enabled = enable;
-}
-
-static void keyboard_enable(int enable)
-{
- if (!keyboard_enabled && enable)
- CPRINTS("KB enable");
- else if (keyboard_enabled && !enable)
- CPRINTS("KB disable");
-
- keyboard_enabled = enable;
-}
-
-static void aux_enable(int enable)
-{
- if (!aux_chan_enabled && enable)
- CPRINTS("AUX enabled");
- else if (aux_chan_enabled && !enable)
- CPRINTS("AUX disabled");
-
- aux_chan_enabled = enable;
-}
-
-static uint8_t read_ctl_ram(uint8_t addr)
-{
- if (addr < ARRAY_SIZE(controller_ram))
- return controller_ram[addr];
- else
- return 0;
-}
-
-/**
- * Manipulate the controller_ram[].
- *
- * Some bits change may trigger internal state change.
- */
-static void update_ctl_ram(uint8_t addr, uint8_t data)
-{
- uint8_t orig;
-
- if (addr >= ARRAY_SIZE(controller_ram))
- return;
-
- orig = controller_ram[addr];
- controller_ram[addr] = data;
- CPRINTS5("KB set CTR_RAM(0x%02x)=0x%02x (old:0x%02x)",
- addr, data, orig);
-
- if (addr == 0x00) {
- /* Keyboard enable/disable */
-
- /* Enable IRQ before enable keyboard (queue chars to host) */
- if (!(orig & I8042_ENIRQ1) && (data & I8042_ENIRQ1))
- keyboard_enable_irq(1);
- if (!(orig & I8042_ENIRQ12) && (data & I8042_ENIRQ12))
- aux_enable_irq(1);
-
- /* Handle the I8042_KBD_DIS bit */
- keyboard_enable(!(data & I8042_KBD_DIS));
-
- /* Handle the I8042_AUX_DIS bit */
- aux_enable(!(data & I8042_AUX_DIS));
-
- /*
- * Disable IRQ after disable keyboard so that every char must
- * have informed the host.
- */
- if ((orig & I8042_ENIRQ1) && !(data & I8042_ENIRQ1))
- keyboard_enable_irq(0);
- if ((orig & I8042_ENIRQ12) && !(data & I8042_ENIRQ12))
- aux_enable_irq(0);
- }
-}
-
-/**
- * Handle the port 0x60 writes from host.
- *
- * Returns 1 if the event was handled.
- */
-static int handle_mouse_data(uint8_t data, uint8_t *output, int *count)
-{
- int out_len = 0;
-
- switch (data_port_state) {
- case STATE_ECHO_MOUSE:
- CPRINTS5("STATE_ECHO_MOUSE: 0x%02x", data);
- output[out_len++] = data;
- data_port_state = STATE_NORMAL;
- break;
-
- case STATE_SEND_TO_MOUSE:
- CPRINTS5("STATE_SEND_TO_MOUSE: 0x%02x", data);
- send_aux_data_to_device(data);
- data_port_state = STATE_NORMAL;
- break;
-
- default: /* STATE_NORMAL */
- return 0;
- }
-
- ASSERT(out_len <= MAX_SCAN_CODE_LEN);
-
- *count = out_len;
-
- return 1;
-}
-
-/**
- * Handle the port 0x60 writes from host.
- *
- * This functions returns the number of bytes stored in *output buffer.
- */
-static int handle_keyboard_data(uint8_t data, uint8_t *output)
-{
- int out_len = 0;
- int save_for_resend = 1;
- int i;
-
- switch (data_port_state) {
- case STATE_SCANCODE:
- CPRINTS5("KB eaten by STATE_SCANCODE: 0x%02x", data);
- if (data == SCANCODE_GET_SET) {
- output[out_len++] = I8042_RET_ACK;
- output[out_len++] = scancode_set;
- } else {
- scancode_set = data;
- CPRINTS("KB scancode set to %d", scancode_set);
- output[out_len++] = I8042_RET_ACK;
- }
- data_port_state = STATE_NORMAL;
- break;
-
- case STATE_SETLEDS:
- CPRINTS5("KB eaten by STATE_SETLEDS");
- output[out_len++] = I8042_RET_ACK;
- data_port_state = STATE_NORMAL;
- break;
-
- case STATE_EX_SETLEDS_1:
- CPRINTS5("KB eaten by STATE_EX_SETLEDS_1");
- output[out_len++] = I8042_RET_ACK;
- data_port_state = STATE_EX_SETLEDS_2;
- break;
-
- case STATE_EX_SETLEDS_2:
- CPRINTS5("KB eaten by STATE_EX_SETLEDS_2");
- output[out_len++] = I8042_RET_ACK;
- data_port_state = STATE_NORMAL;
- break;
-
- case STATE_WRITE_CMD_BYTE:
- CPRINTS5("KB eaten by STATE_WRITE_CMD_BYTE: 0x%02x",
- data);
- update_ctl_ram(controller_ram_address, data);
- data_port_state = STATE_NORMAL;
- break;
-
- case STATE_WRITE_OUTPUT_PORT:
- CPRINTS5("KB eaten by STATE_WRITE_OUTPUT_PORT: 0x%02x",
- data);
- A20_status = (data & BIT(1)) ? 1 : 0;
- data_port_state = STATE_NORMAL;
- break;
-
- case STATE_SETREP:
- CPRINTS5("KB eaten by STATE_SETREP: 0x%02x", data);
- set_typematic_delays(data);
-
- output[out_len++] = I8042_RET_ACK;
- data_port_state = STATE_NORMAL;
- break;
-
- default: /* STATE_NORMAL */
- switch (data) {
- case I8042_CMD_GSCANSET: /* also I8042_CMD_SSCANSET */
- output[out_len++] = I8042_RET_ACK;
- data_port_state = STATE_SCANCODE;
- break;
-
- case I8042_CMD_SETLEDS:
- /* Chrome OS doesn't have keyboard LEDs, so ignore */
- output[out_len++] = I8042_RET_ACK;
- data_port_state = STATE_SETLEDS;
- break;
-
- case I8042_CMD_EX_SETLEDS:
- output[out_len++] = I8042_RET_ACK;
- data_port_state = STATE_EX_SETLEDS_1;
- break;
-
- case I8042_CMD_DIAG_ECHO:
- output[out_len++] = I8042_RET_ACK;
- output[out_len++] = I8042_CMD_DIAG_ECHO;
- break;
-
- case I8042_CMD_GETID: /* fall-thru */
- case I8042_CMD_OK_GETID:
- output[out_len++] = I8042_RET_ACK;
- output[out_len++] = 0xab; /* Regular keyboards */
- output[out_len++] = 0x83;
- break;
-
- case I8042_CMD_SETREP:
- output[out_len++] = I8042_RET_ACK;
- data_port_state = STATE_SETREP;
- break;
-
- case I8042_CMD_ENABLE:
- output[out_len++] = I8042_RET_ACK;
- keystroke_enable(1);
- keyboard_clear_buffer();
- break;
-
- case I8042_CMD_RESET_DIS:
- output[out_len++] = I8042_RET_ACK;
- keystroke_enable(0);
- reset_rate_and_delay();
- keyboard_clear_buffer();
- break;
-
- case I8042_CMD_RESET_DEF:
- output[out_len++] = I8042_RET_ACK;
- reset_rate_and_delay();
- keyboard_clear_buffer();
- break;
-
- case I8042_CMD_RESET:
- reset_rate_and_delay();
- keyboard_clear_buffer();
- output[out_len++] = I8042_RET_ACK;
- break;
-
- case I8042_CMD_RESEND:
- save_for_resend = 0;
- for (i = 0; i < resend_command_len; ++i)
- output[out_len++] = resend_command[i];
- break;
-
- case 0x60: /* fall-thru */
- case 0x45:
- /* U-boot hack. Just ignore; don't reply. */
- break;
-
- case I8042_CMD_SETALL_MB: /* fall-thru */
- case I8042_CMD_SETALL_MBR:
- case I8042_CMD_EX_ENABLE:
- default:
- output[out_len++] = I8042_RET_NAK;
- CPRINTS("KB Unsupported i8042 data 0x%02x",
- data);
- break;
- }
- }
-
- /* For resend, keep output before leaving. */
- if (out_len && save_for_resend) {
- ASSERT(out_len <= MAX_SCAN_CODE_LEN);
- for (i = 0; i < out_len; ++i)
- resend_command[i] = output[i];
- resend_command_len = out_len;
- }
-
- ASSERT(out_len <= MAX_SCAN_CODE_LEN);
- return out_len;
-}
-
-/**
- * Handle the port 0x64 writes from host.
- *
- * This functions returns the number of bytes stored in *output buffer.
- * BUT those bytes will appear at port 0x60.
- */
-static int handle_keyboard_command(uint8_t command, uint8_t *output)
-{
- int out_len = 0;
-
- CPRINTS5("KB recv cmd: 0x%02x", command);
- kblog_put('c', command);
-
- switch (command) {
- case I8042_READ_CMD_BYTE:
- /*
- * Ensure that the keyboard buffer is cleared before adding
- * command byte to it. Since the host is asking for command
- * byte, sending it buffered key press data can confuse the
- * host and result in it taking incorrect action.
- */
- keyboard_clear_buffer();
- output[out_len++] = read_ctl_ram(0);
- break;
-
- case I8042_WRITE_CMD_BYTE:
- data_port_state = STATE_WRITE_CMD_BYTE;
- controller_ram_address = command - 0x60;
- break;
-
- case I8042_DIS_KB:
- update_ctl_ram(0, read_ctl_ram(0) | I8042_KBD_DIS);
- reset_rate_and_delay();
- typematic_len = 0; /* stop typematic */
- keyboard_clear_buffer();
- break;
-
- case I8042_ENA_KB:
- update_ctl_ram(0, read_ctl_ram(0) & ~I8042_KBD_DIS);
- keystroke_enable(1);
- keyboard_clear_buffer();
- break;
-
- case I8042_READ_OUTPUT_PORT:
- output[out_len++] =
- (lpc_keyboard_input_pending() ? BIT(5) : 0) |
- (lpc_keyboard_has_char() ? BIT(4) : 0) |
- (A20_status ? BIT(1) : 0) |
- 1; /* Main processor in normal mode */
- break;
-
- case I8042_WRITE_OUTPUT_PORT:
- data_port_state = STATE_WRITE_OUTPUT_PORT;
- break;
-
- case I8042_RESET_SELF_TEST:
- output[out_len++] = 0x55; /* Self test success */
- break;
-
- case I8042_TEST_KB_PORT:
- output[out_len++] = 0x00;
- break;
-
- case I8042_DIS_MOUSE:
- update_ctl_ram(0, read_ctl_ram(0) | I8042_AUX_DIS);
- break;
-
- case I8042_ENA_MOUSE:
- update_ctl_ram(0, read_ctl_ram(0) & ~I8042_AUX_DIS);
- break;
-
- case I8042_TEST_MOUSE:
- output[out_len++] = 0; /* No error detected */
- break;
-
- case I8042_ECHO_MOUSE:
- data_port_state = STATE_ECHO_MOUSE;
- break;
-
- case I8042_SEND_TO_MOUSE:
- data_port_state = STATE_SEND_TO_MOUSE;
- break;
-
- case I8042_SYSTEM_RESET:
- chipset_reset(CHIPSET_RESET_KB_SYSRESET);
- break;
-
- default:
- if (command >= I8042_READ_CTL_RAM &&
- command <= I8042_READ_CTL_RAM_END) {
- output[out_len++] = read_ctl_ram(command - 0x20);
- } else if (command >= I8042_WRITE_CTL_RAM &&
- command <= I8042_WRITE_CTL_RAM_END) {
- data_port_state = STATE_WRITE_CMD_BYTE;
- controller_ram_address = command - 0x60;
- } else if (command == I8042_DISABLE_A20) {
- A20_status = 0;
- } else if (command == I8042_ENABLE_A20) {
- A20_status = 1;
- } else if (command >= I8042_PULSE_START &&
- command <= I8042_PULSE_END) {
- /* Pulse Output Bits,
- * b0=0 to reset CPU, see I8042_SYSTEM_RESET above
- * b1=0 to disable A20 line
- */
- A20_status = command & BIT(1) ? 1 : 0;
- } else {
- CPRINTS("KB unsupported cmd: 0x%02x", command);
- reset_rate_and_delay();
- keyboard_clear_buffer();
- output[out_len++] = I8042_RET_NAK;
- data_port_state = STATE_NORMAL;
- }
- break;
- }
-
- return out_len;
-}
-
-static void i8042_handle_from_host(void)
-{
- struct host_byte h;
- int ret_len;
- uint8_t output[MAX_SCAN_CODE_LEN];
- uint8_t chan = CHAN_KBD;
-
- while (queue_remove_unit(&from_host, &h)) {
- if (h.type == HOST_COMMAND) {
- ret_len = handle_keyboard_command(h.byte, output);
- } else {
- CPRINTS5("KB recv data: 0x%02x", h.byte);
- kblog_put('d', h.byte);
-
- if (IS_ENABLED(CONFIG_8042_AUX) &&
- handle_mouse_data(h.byte, output, &ret_len))
- chan = CHAN_AUX;
- else
- ret_len = handle_keyboard_data(h.byte, output);
- }
-
- i8042_send_to_host(ret_len, output, chan);
- }
-}
-
-void keyboard_protocol_task(void *u)
-{
- int wait = -1;
- int retries = 0;
-
- reset_rate_and_delay();
-
- while (1) {
- /* Wait for next host read/write */
- task_wait_event(wait);
-
- while (1) {
- timestamp_t t = get_time();
- struct data_byte entry;
-
- /* Handle typematic */
- if (!typematic_len) {
- /* Typematic disabled; wait for enable */
- wait = -1;
- } else if (timestamp_expired(typematic_deadline, &t)) {
- /* Ready for next typematic keystroke */
- if (keystroke_enabled)
- i8042_send_to_host(typematic_len,
- typematic_scan_code,
- CHAN_KBD);
- typematic_deadline.val = t.val +
- typematic_inter_delay;
- wait = typematic_inter_delay;
- } else {
- /* Wait for remaining interval */
- wait = typematic_deadline.val - t.val;
- }
-
- /* Handle command/data write from host */
- i8042_handle_from_host();
-
- /* Check if we have data to send to host */
- if (queue_is_empty(&to_host))
- break;
-
- /* Handle data waiting for host */
- if (lpc_keyboard_has_char()) {
- /* If interrupts disabled, nothing we can do */
- if (!i8042_keyboard_irq_enabled &&
- !i8042_aux_irq_enabled)
- break;
-
- /* Give the host a little longer to respond */
- if (++retries < KB_TO_HOST_RETRIES)
- break;
-
- /*
- * We keep getting data, but the host keeps
- * ignoring us. Fine, we're done waiting.
- * Hey, host, are you ever gonna get to this
- * data? Send it another interrupt in case it
- * somehow missed the first one.
- */
- CPRINTS("KB extra IRQ");
- lpc_keyboard_resume_irq();
- retries = 0;
- break;
- }
-
- /* Get a char from buffer. */
- kblog_put('k', to_host.state->head);
- queue_remove_unit(&to_host, &entry);
-
- /* Write to host. */
- if (entry.chan == CHAN_AUX &&
- IS_ENABLED(CONFIG_8042_AUX)) {
- kblog_put('A', entry.byte);
- lpc_aux_put_char(entry.byte,
- i8042_aux_irq_enabled);
- } else {
- kblog_put('K', entry.byte);
- lpc_keyboard_put_char(
- entry.byte, i8042_keyboard_irq_enabled);
- }
- retries = 0;
- }
- }
-}
-
-static void send_aux_data_to_host_deferred(void)
-{
- uint8_t data;
-
- if (IS_ENABLED(CONFIG_DEVICE_EVENT) &&
- chipset_in_state(CHIPSET_STATE_ANY_SUSPEND))
- device_set_single_event(EC_DEVICE_EVENT_TRACKPAD);
-
- while (!queue_is_empty(&aux_to_host_queue)) {
- queue_remove_unit(&aux_to_host_queue, &data);
- if (aux_chan_enabled && IS_ENABLED(CONFIG_8042_AUX))
- i8042_send_to_host(1, &data, CHAN_AUX);
- else
- CPRINTS("AUX Callback ignored");
- }
-}
-DECLARE_DEFERRED(send_aux_data_to_host_deferred);
-
-/**
- * Send aux data to host from interrupt context.
- *
- * @param data Aux response to send to host.
- */
-void send_aux_data_to_host_interrupt(uint8_t data)
-{
- queue_add_unit(&aux_to_host_queue, &data);
- hook_call_deferred(&send_aux_data_to_host_deferred_data, 0);
-}
-
-/**
- * Handle button changing state.
- *
- * @param button Type of button that changed
- * @param is_pressed Whether the button was pressed or released
- */
-test_mockable void keyboard_update_button(enum keyboard_button_type button,
- int is_pressed)
-{
- uint8_t scan_code[MAX_SCAN_CODE_LEN];
- uint32_t len;
- struct button_8042_t button_8042;
- enum scancode_set_list code_set;
-
- /*
- * Only send the scan code if main chipset is fully awake and
- * keystrokes are enabled.
- */
- if (!chipset_in_state(CHIPSET_STATE_ON) || !keystroke_enabled)
- return;
-
- code_set = acting_code_set(scancode_set);
- if (!is_supported_code_set(code_set))
- return;
-
- button_8042 = buttons_8042[button];
- scancode_bytes(button_8042.scancode, is_pressed, code_set, scan_code,
- &len);
- ASSERT(len > 0);
-
- if (button_8042.repeat) {
- if (is_pressed)
- set_typematic_key(scan_code, len);
- else
- clear_typematic_key();
- }
-
- if (keystroke_enabled) {
- i8042_send_to_host(len, scan_code, CHAN_KBD);
- task_wake(TASK_ID_KEYPROTO);
- }
-}
-
-/*****************************************************************************/
-/* Console commands */
-#ifdef CONFIG_CMD_KEYBOARD
-static int command_typematic(int argc, char **argv)
-{
- int i;
-
- if (argc == 3) {
- typematic_first_delay = strtoi(argv[1], NULL, 0) * MSEC;
- typematic_inter_delay = strtoi(argv[2], NULL, 0) * MSEC;
- }
-
- ccprintf("From host: 0x%02x\n", typematic_value_from_host);
- ccprintf("First delay: %3d ms\n", typematic_first_delay / 1000);
- ccprintf("Inter delay: %3d ms\n", typematic_inter_delay / 1000);
- ccprintf("Now: %.6" PRId64 "\n", get_time().val);
- ccprintf("Deadline: %.6" PRId64 "\n", typematic_deadline.val);
-
- ccputs("Repeat scan code: {");
- for (i = 0; i < typematic_len; ++i)
- ccprintf("0x%02x, ", typematic_scan_code[i]);
- ccputs("}\n");
- return EC_SUCCESS;
-}
-
-static int command_codeset(int argc, char **argv)
-{
- if (argc == 2) {
- int set = strtoi(argv[1], NULL, 0);
- switch (set) {
- case SCANCODE_SET_1: /* fall-thru */
- case SCANCODE_SET_2: /* fall-thru */
- scancode_set = set;
- break;
- default:
- return EC_ERROR_PARAM1;
- }
- }
-
- ccprintf("Set: %d\n", scancode_set);
- ccprintf("I8042_XLATE: %d\n", controller_ram[0] & I8042_XLATE ? 1 : 0);
- return EC_SUCCESS;
-}
-
-static int command_controller_ram(int argc, char **argv)
-{
- int index;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- index = strtoi(argv[1], NULL, 0);
- if (index >= ARRAY_SIZE(controller_ram))
- return EC_ERROR_PARAM1;
-
- if (argc >= 3)
- update_ctl_ram(index, strtoi(argv[2], NULL, 0));
-
- ccprintf("%d = 0x%02x\n", index, controller_ram[index]);
- return EC_SUCCESS;
-}
-
-static int command_keyboard_log(int argc, char **argv)
-{
- int i;
-
- /* If no args, print log */
- if (argc == 1) {
- ccprintf("KBC log (len=%d):\n", kblog_len);
- for (i = 0; kblog_buf && i < kblog_len; ++i) {
- ccprintf("%c.%02x ",
- kblog_buf[i].type, kblog_buf[i].byte);
- if ((i & 15) == 15) {
- ccputs("\n");
- cflush();
- }
- }
- ccputs("\n");
- return EC_SUCCESS;
- }
-
- /* Otherwise, enable/disable */
- if (!parse_bool(argv[1], &i))
- return EC_ERROR_PARAM1;
-
- if (i) {
- if (!kblog_buf) {
- int rv = SHARED_MEM_ACQUIRE_CHECK(
- sizeof(*kblog_buf) * MAX_KBLOG,
- (char **)&kblog_buf);
- if (rv != EC_SUCCESS)
- kblog_buf = NULL;
- kblog_len = 0;
- return rv;
- }
- } else {
- kblog_len = 0;
- if (kblog_buf)
- shared_mem_release(kblog_buf);
- kblog_buf = NULL;
- }
-
- return EC_SUCCESS;
-}
-
-static int command_keyboard(int argc, char **argv)
-{
- int ena;
-
- if (argc > 1) {
- if (!parse_bool(argv[1], &ena))
- return EC_ERROR_PARAM1;
-
- keyboard_enable(ena);
- }
-
- ccprintf("Enabled: %d\n", keyboard_enabled);
- return EC_SUCCESS;
-}
-
-static int command_8042_internal(int argc, char **argv)
-{
- int i;
-
- ccprintf("data_port_state=%d\n", data_port_state);
- ccprintf("i8042_keyboard_irq_enabled=%d\n", i8042_keyboard_irq_enabled);
- ccprintf("i8042_aux_irq_enabled=%d\n", i8042_aux_irq_enabled);
- ccprintf("keyboard_enabled=%d\n", keyboard_enabled);
- ccprintf("keystroke_enabled=%d\n", keystroke_enabled);
- ccprintf("aux_chan_enabled=%d\n", aux_chan_enabled);
-
- ccprintf("resend_command[]={");
- for (i = 0; i < resend_command_len; i++)
- ccprintf("0x%02x, ", resend_command[i]);
- ccprintf("}\n");
-
- ccprintf("controller_ram_address=0x%02x\n", controller_ram_address);
- ccprintf("A20_status=%d\n", A20_status);
-
- ccprintf("from_host[]={");
- for (i = 0; i < queue_count(&from_host); ++i) {
- struct host_byte entry;
-
- queue_peek_units(&from_host, &entry, i, 1);
-
- ccprintf("0x%02x, 0x%02x, ", entry.type, entry.byte);
- }
- ccprintf("}\n");
-
- ccprintf("to_host[]={");
- for (i = 0; i < queue_count(&to_host); ++i) {
- struct data_byte entry;
-
- queue_peek_units(&to_host, &entry, i, 1);
-
- ccprintf("0x%02x%s, ", entry.byte,
- entry.chan == CHAN_AUX ? " aux" : "");
- }
- ccprintf("}\n");
-
- return EC_SUCCESS;
-}
-
-/* Zephyr only provides these as subcommands*/
-#ifndef CONFIG_ZEPHYR
-DECLARE_CONSOLE_COMMAND(typematic, command_typematic,
- "[first] [inter]",
- "Get/set typematic delays");
-DECLARE_CONSOLE_COMMAND(codeset, command_codeset,
- "[set]",
- "Get/set keyboard codeset");
-DECLARE_CONSOLE_COMMAND(ctrlram, command_controller_ram,
- "index [value]",
- "Get/set keyboard controller RAM");
-DECLARE_CONSOLE_COMMAND(kblog, command_keyboard_log,
- "[on | off]",
- "Print or toggle keyboard event log");
-DECLARE_CONSOLE_COMMAND(kbd, command_keyboard,
- "[on | off]",
- "Print or toggle keyboard info");
-#endif
-
-static int command_8042(int argc, char **argv)
-{
- if (argc >= 2) {
- if (!strcasecmp(argv[1], "internal"))
- return command_8042_internal(argc, argv);
- else if (!strcasecmp(argv[1], "typematic"))
- return command_typematic(argc - 1, argv + 1);
- else if (!strcasecmp(argv[1], "codeset"))
- return command_codeset(argc - 1, argv + 1);
- else if (!strcasecmp(argv[1], "ctrlram"))
- return command_controller_ram(argc - 1, argv + 1);
- else if (CMD_KEYBOARD_LOG && !strcasecmp(argv[1], "kblog"))
- return command_keyboard_log(argc - 1, argv + 1);
- else if (!strcasecmp(argv[1], "kbd"))
- return command_keyboard(argc - 1, argv + 1);
- else
- return EC_ERROR_PARAM1;
- } else {
- char *ctlram_argv[] = {"ctrlram", "0"};
-
- ccprintf("\n- Typematic:\n");
- command_typematic(argc, argv);
- ccprintf("\n- Codeset:\n");
- command_codeset(argc, argv);
- ccprintf("\n- Control RAM:\n");
- command_controller_ram(
- sizeof(ctlram_argv) / sizeof(ctlram_argv[0]),
- ctlram_argv);
- if (CMD_KEYBOARD_LOG) {
- ccprintf("\n- Keyboard log:\n");
- command_keyboard_log(argc, argv);
- }
- ccprintf("\n- Keyboard:\n");
- command_keyboard(argc, argv);
- ccprintf("\n- Internal:\n");
- command_8042_internal(argc, argv);
- ccprintf("\n");
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(8042, command_8042,
- "[internal | typematic | codeset | ctrlram |"
- " kblog | kbd]",
- "Print 8042 state in one place");
-#endif
-
-
-/*****************************************************************************/
-/* Hooks */
-
-/**
- * Preserve the states of keyboard controller to keep the initialized states
- * between reboot_ec commands. Saving info include:
- *
- * - code set
- * - controller_ram[0]:
- * - XLATE
- * - KB/TP disabled
- * - KB/TP IRQ enabled
- */
-static void keyboard_preserve_state(void)
-{
- struct kb_state state;
-
- state.codeset = scancode_set;
- state.ctlram = controller_ram[0];
- state.keystroke_enabled = keystroke_enabled;
-
- system_add_jump_tag(KB_SYSJUMP_TAG, KB_HOOK_VERSION,
- sizeof(state), &state);
-}
-DECLARE_HOOK(HOOK_SYSJUMP, keyboard_preserve_state, HOOK_PRIO_DEFAULT);
-
-/**
- * Restore the keyboard states after reboot_ec command. See above function.
- */
-static void keyboard_restore_state(void)
-{
- const struct kb_state *prev;
- int version, size;
-
- prev = (const struct kb_state *)system_get_jump_tag(KB_SYSJUMP_TAG,
- &version, &size);
- if (prev && version == KB_HOOK_VERSION && size == sizeof(*prev)) {
- /* Coming back from a sysjump, so restore settings. */
- scancode_set = prev->codeset;
- update_ctl_ram(0, prev->ctlram);
- keystroke_enabled = prev->keystroke_enabled;
- }
-}
-DECLARE_HOOK(HOOK_INIT, keyboard_restore_state, HOOK_PRIO_DEFAULT);
-
-#if defined(CONFIG_POWER_BUTTON) && !defined(CONFIG_MKBP_INPUT_DEVICES)
-/**
- * Handle power button changing state.
- */
-static void keyboard_power_button(void)
-{
- keyboard_update_button(KEYBOARD_BUTTON_POWER,
- power_button_is_pressed());
-}
-DECLARE_HOOK(HOOK_POWER_BUTTON_CHANGE, keyboard_power_button,
- HOOK_PRIO_DEFAULT);
-
-#endif /* CONFIG_POWER_BUTTON && !CONFIG_MKBP_INPUT_DEVICES */
-
diff --git a/common/keyboard_8042_sharedlib.c b/common/keyboard_8042_sharedlib.c
deleted file mode 100644
index 1d024d3f47..0000000000
--- a/common/keyboard_8042_sharedlib.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/* Copyright 2015 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.
- *
- * Objects which can be shared between RO and RW for 8042 keyboard protocol.
- */
-
-#include "button.h"
-#include "keyboard_8042_sharedlib.h"
-#include "keyboard_config.h"
-#include "keyboard_protocol.h"
-#include "libsharedobjs.h"
-#include "util.h"
-
-#ifndef CONFIG_KEYBOARD_CUSTOMIZATION
-/* The standard Chrome OS keyboard matrix table in scan code set 2. */
-static uint16_t scancode_set2[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = {
- {0x0000, 0x0000, 0x0014, 0xe01f, 0xe014, 0xe007, 0x0000, 0x0000},
- {0xe01f, 0x0076, 0x000d, 0x000e, 0x001c, 0x001a, 0x0016, 0x0015},
- {0x0005, 0x000c, 0x0004, 0x0006, 0x0023, 0x0021, 0x0026, 0x0024},
- {0x0032, 0x0034, 0x002c, 0x002e, 0x002b, 0x002a, 0x0025, 0x002d},
- {0x0009, 0x0083, 0x000b, 0x0003, 0x001b, 0x0022, 0x001e, 0x001d},
- {0x0051, 0x0000, 0x005b, 0x0000, 0x0042, 0x0041, 0x003e, 0x0043},
- {0x0031, 0x0033, 0x0035, 0x0036, 0x003b, 0x003a, 0x003d, 0x003c},
- {0x0000, 0x0000, 0x0061, 0x0000, 0x0000, 0x0012, 0x0000, 0x0059},
- {0x0055, 0x0052, 0x0054, 0x004e, 0x004c, 0x004a, 0x0045, 0x004d},
- {0x0000, 0x0001, 0x000a, 0x002f, 0x004b, 0x0049, 0x0046, 0x0044},
- {0xe011, 0x0000, 0x006a, 0x0000, 0x005d, 0x0000, 0x0011, 0x0000},
-#ifndef CONFIG_KEYBOARD_KEYPAD
- {0x0000, 0x0066, 0x0000, 0x005d, 0x005a, 0x0029, 0xe072, 0xe075},
- {0x0000, 0x0064, 0x0000, 0x0067, 0x0000, 0x0000, 0xe074, 0xe06b},
-#else
- {0x0000, 0x0066, 0xe071, 0x005d, 0x005a, 0x0029, 0xe072, 0xe075},
- {0xe06c, 0x0064, 0xe07d, 0x0067, 0xe069, 0xe07a, 0xe074, 0xe06b},
- {0xe04a, 0x007c, 0x007b, 0x0074, 0x0071, 0x0073, 0x006b, 0x0070},
- {0x006c, 0x0075, 0x007d, 0x0079, 0x007a, 0x0072, 0x0069, 0xe05a},
-#endif
-};
-
-uint16_t get_scancode_set2(uint8_t row, uint8_t col)
-{
- if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS)
- return scancode_set2[col][row];
- return 0;
-}
-
-void set_scancode_set2(uint8_t row, uint8_t col, uint16_t val)
-{
- if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS)
- scancode_set2[col][row] = val;
-}
-
-#endif /* CONFIG_KEYBOARD_CUSTOMIZATION */
-
-/*
- * The translation table from scan code set 2 to set 1.
- * Ref: http://kbd-project.org/docs/scancodes/scancodes-10.html#ss10.3
- * To reduce space, we only keep the translation for 0~127,
- * so a real translation need to do 0x83=>0x41 explicitly (
- * see scancode_translate_set2_to_1 below).
- */
-SHAREDLIB(const uint8_t scancode_translate_table[128] = {
- 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58,
- 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
- 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a,
- 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
- 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c,
- 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
- 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e,
- 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
- 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60,
- 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
- 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e,
- 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
- 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b,
- 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
- 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45,
- 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
-});
-
-
-#ifdef CONFIG_KEYBOARD_DEBUG
-SHAREDLIB(const
-static char * const keycap_long_label[KLLI_MAX & KEYCAP_LONG_LABEL_INDEX_BITMASK] = {
- "UNKNOWN", "F1", "F2", "F3",
- "F4", "F5", "F6", "F7",
- "F8", "F9", "F10", "F11",
- "F12", "F13", "F14", "F15",
- "L-ALT", "R-ALT", "L-CTR", "R-CTR",
- "L-SHT", "R-SHT", "ENTER", "SPACE",
- "B-SPC", "TAB", "SEARC", "LEFT",
- "RIGHT", "DOWN", "UP", "ESC",
-});
-
-const char *get_keycap_long_label(uint8_t idx)
-{
- if (idx < ARRAY_SIZE(keycap_long_label))
- return keycap_long_label[idx];
- return "UNKNOWN";
-}
-
-#ifndef CONFIG_KEYBOARD_CUSTOMIZATION
-static char keycap_label[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = {
- {KLLI_UNKNO, KLLI_UNKNO, KLLI_L_CTR, KLLI_SEARC,
- KLLI_R_CTR, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO},
- {KLLI_F11, KLLI_ESC, KLLI_TAB, '~',
- 'a', 'z', '1', 'q'},
- {KLLI_F1, KLLI_F4, KLLI_F3, KLLI_F2,
- 'd', 'c', '3', 'e'},
- {'b', 'g', 't', '5',
- 'f', 'v', '4', 'r'},
- {KLLI_F10, KLLI_F7, KLLI_F6, KLLI_F5,
- 's', 'x', '2', 'w'},
- {KLLI_UNKNO, KLLI_F12, ']', KLLI_F13,
- 'k', ',', '8', 'i'},
- {'n', 'h', 'y', '6',
- 'j', 'm', '7', 'u'},
- {KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO,
- KLLI_UNKNO, KLLI_L_SHT, KLLI_UNKNO, KLLI_R_SHT},
- {'=', '\'', '[', '-',
- ';', '/', '0', 'p'},
- {KLLI_F14, KLLI_F9, KLLI_F8, KLLI_UNKNO,
- '|', '.', '9', 'o'},
- {KLLI_R_ALT, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO,
- KLLI_UNKNO, KLLI_UNKNO, KLLI_L_ALT, KLLI_UNKNO},
- {KLLI_F15, KLLI_B_SPC, KLLI_UNKNO, '\\',
- KLLI_ENTER, KLLI_SPACE, KLLI_DOWN, KLLI_UP},
- {KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO,
- KLLI_UNKNO, KLLI_UNKNO, KLLI_RIGHT, KLLI_LEFT},
-#ifdef CONFIG_KEYBOARD_KEYPAD
- /* TODO: Populate these */
- {KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO,
- KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO},
- {KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO,
- KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO, KLLI_UNKNO},
-#endif
-};
-
-char get_keycap_label(uint8_t row, uint8_t col)
-{
- if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS)
- return keycap_label[col][row];
- return KLLI_UNKNO;
-}
-
-void set_keycap_label(uint8_t row, uint8_t col, char val)
-{
- if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS)
- keycap_label[col][row] = val;
-}
-#endif /* CONFIG_KEYBOARD_CUSTOMIZATION */
-#endif /* CONFIG_KEYBOARD_DEBUG */
-
-uint8_t scancode_translate_set2_to_1(uint8_t code)
-{
- if (code & 0x80) {
- if (code == 0x83)
- return 0x41;
- return code;
- }
- return scancode_translate_table[code];
-}
-
-/*
- * Button scan codes.
- * Must be in the same order as defined in keyboard_button_type.
- */
-SHAREDLIB(const struct button_8042_t buttons_8042[] = {
- {SCANCODE_POWER, 0},
- {SCANCODE_VOLUME_DOWN, 1},
- {SCANCODE_VOLUME_UP, 1},
- {SCANCODE_1, 1},
- {SCANCODE_2, 1},
- {SCANCODE_3, 1},
- {SCANCODE_4, 1},
- {SCANCODE_5, 1},
- {SCANCODE_6, 1},
- {SCANCODE_7, 1},
- {SCANCODE_8, 1},
-});
-BUILD_ASSERT(ARRAY_SIZE(buttons_8042) == KEYBOARD_BUTTON_COUNT);
diff --git a/common/keyboard_backlight.c b/common/keyboard_backlight.c
deleted file mode 100644
index 82312e0776..0000000000
--- a/common/keyboard_backlight.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/* Copyright 2018 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.
- */
-
-#include "console.h"
-#include "ec_commands.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "keyboard_backlight.h"
-#include "lid_switch.h"
-#include "timer.h"
-#include "util.h"
-
-#define CPRINTF(format, args...) cprintf(CC_KEYBOARD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args)
-
-static struct kblight_conf kblight;
-static int current_percent;
-
-void __attribute__((weak)) board_kblight_init(void)
-{ }
-
-static int kblight_init(void)
-{
- if (!kblight.drv || !kblight.drv->init)
- return EC_ERROR_UNIMPLEMENTED;
- return kblight.drv->init();
-}
-
-static void kblight_set_deferred(void)
-{
- if (!kblight.drv || !kblight.drv->set)
- return;
- kblight.drv->set(current_percent);
-}
-DECLARE_DEFERRED(kblight_set_deferred);
-
-/*
- * APIs
- */
-int kblight_set(int percent)
-{
- if (percent < 0 || 100 < percent)
- return EC_ERROR_INVAL;
- current_percent = percent;
- /* Need to defer i2c in case it's called from an interrupt handler. */
- hook_call_deferred(&kblight_set_deferred_data, 0);
- return EC_SUCCESS;
-}
-
-int kblight_get(void)
-{
- return current_percent;
-}
-
-int kblight_enable(int enable)
-{
-#ifdef GPIO_EN_KEYBOARD_BACKLIGHT
- gpio_set_level(GPIO_EN_KEYBOARD_BACKLIGHT, enable);
-#endif
- if (!kblight.drv || !kblight.drv->enable)
- return -1;
- return kblight.drv->enable(enable);
-}
-
-int kblight_register(const struct kblight_drv *drv)
-{
- kblight.drv = drv;
- CPRINTS("kblight registered");
- return EC_SUCCESS;
-}
-
-/*
- * Hooks
- */
-static void keyboard_backlight_init(void)
-{
- /* Uses PWM by default. Can be customized by board_kblight_init */
-#ifdef CONFIG_PWM_KBLIGHT
- kblight_register(&kblight_pwm);
-#endif
- board_kblight_init();
- if (kblight_init())
- CPRINTS("kblight init failed");
- /* Don't leave kblight enable state undetermined */
- kblight_enable(0);
-}
-DECLARE_HOOK(HOOK_INIT, keyboard_backlight_init, HOOK_PRIO_DEFAULT);
-
-static void kblight_suspend(void)
-{
- kblight_enable(0);
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, kblight_suspend, HOOK_PRIO_DEFAULT);
-
-static void kblight_resume(void)
-{
- if (lid_is_open() && current_percent) {
- kblight_enable(1);
- kblight_set(current_percent);
- }
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, kblight_resume, HOOK_PRIO_DEFAULT);
-
-static void kblight_lid_change(void)
-{
- kblight_enable(lid_is_open() && current_percent);
-}
-DECLARE_HOOK(HOOK_LID_CHANGE, kblight_lid_change, HOOK_PRIO_DEFAULT);
-
-/*
- * Console and host commands
- */
-static int cc_kblight(int argc, char **argv)
-{
- if (argc >= 2) {
- char *e;
- int i = strtoi(argv[1], &e, 0);
- if (*e)
- return EC_ERROR_PARAM1;
- if (kblight_set(i))
- return EC_ERROR_PARAM1;
- if (kblight_enable(i > 0))
- return EC_ERROR_PARAM1;
- }
- ccprintf("Keyboard backlight: %d%%\n", kblight_get());
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(kblight, cc_kblight,
- "percent",
- "Get/set keyboard backlight");
-
-enum ec_status hc_get_keyboard_backlight(struct host_cmd_handler_args *args)
-{
- struct ec_response_pwm_get_keyboard_backlight *r = args->response;
-
- r->percent = kblight_get();
- r->enabled = 1; /* Deprecated */
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_KEYBOARD_BACKLIGHT,
- hc_get_keyboard_backlight,
- EC_VER_MASK(0));
-
-enum ec_status hc_set_keyboard_backlight(struct host_cmd_handler_args *args)
-{
- const struct ec_params_pwm_set_keyboard_backlight *p = args->params;
-
- if (kblight_set(p->percent))
- return EC_RES_ERROR;
- if (kblight_enable(p->percent > 0))
- return EC_RES_ERROR;
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_KEYBOARD_BACKLIGHT,
- hc_set_keyboard_backlight,
- EC_VER_MASK(0));
diff --git a/common/keyboard_mkbp.c b/common/keyboard_mkbp.c
deleted file mode 100644
index d8e9f8d909..0000000000
--- a/common/keyboard_mkbp.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/* Copyright 2013 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.
- *
- * MKBP keyboard protocol
- */
-
-#include "chipset.h"
-#include "common.h"
-#include "host_command.h"
-#include "keyboard_config.h"
-#include "keyboard_mkbp.h"
-#include "keyboard_protocol.h"
-#include "keyboard_raw.h"
-#include "keyboard_scan.h"
-#include "keyboard_test.h"
-#include "mkbp_event.h"
-#include "mkbp_fifo.h"
-#include "task.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_KEYBOARD, outstr)
-#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args)
-
-/* Changes to col,row here need to also be reflected in kernel.
- * drivers/input/mkbp.c ... see KEY_BATTERY.
- */
-#define BATTERY_KEY_COL 0
-#define BATTERY_KEY_ROW 7
-#define BATTERY_KEY_ROW_MASK BIT(BATTERY_KEY_ROW)
-
-#ifndef HAS_TASK_KEYSCAN
-#error "Task KEYSCAN has to be enabled for MKBP keyboard"
-#endif /* !defined(HAS_TASK_KEYSCAN) */
-
-/* Config for mkbp protocol; does not include fields from scan config */
-struct ec_mkbp_protocol_config {
- uint32_t valid_mask; /* valid fields */
- uint8_t flags; /* some flags (enum mkbp_config_flags) */
- uint8_t valid_flags; /* which flags are valid */
-
- /* maximum depth to allow for fifo (0 = no keyscan output) */
- uint8_t fifo_max_depth;
-} __packed;
-
-static struct ec_mkbp_protocol_config config = {
- .valid_mask = EC_MKBP_VALID_SCAN_PERIOD | EC_MKBP_VALID_POLL_TIMEOUT |
- EC_MKBP_VALID_MIN_POST_SCAN_DELAY |
- EC_MKBP_VALID_OUTPUT_SETTLE | EC_MKBP_VALID_DEBOUNCE_DOWN |
- EC_MKBP_VALID_DEBOUNCE_UP | EC_MKBP_VALID_FIFO_MAX_DEPTH,
- .valid_flags = EC_MKBP_FLAGS_ENABLE,
- .flags = EC_MKBP_FLAGS_ENABLE,
- .fifo_max_depth = FIFO_DEPTH,
-};
-
-/*****************************************************************************/
-/* Interface */
-
-void keyboard_clear_buffer(void)
-{
- mkbp_fifo_clear_keyboard();
-}
-
-test_mockable int mkbp_keyboard_add(const uint8_t *buffp)
-{
- /*
- * If the keyboard protocol is not enabled, don't save the state to
- * the FIFO or trigger an interrupt.
- */
- if (!(config.flags & EC_MKBP_FLAGS_ENABLE))
- return EC_SUCCESS;
-
- return mkbp_fifo_add((uint8_t)EC_MKBP_EVENT_KEY_MATRIX, buffp);
-}
-
-static int keyboard_get_next_event(uint8_t *out)
-{
- return mkbp_fifo_get_next_event(out, EC_MKBP_EVENT_KEY_MATRIX);
-}
-DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_KEY_MATRIX, keyboard_get_next_event);
-
-void keyboard_send_battery_key(void)
-{
- uint8_t state[KEYBOARD_COLS_MAX];
-
- /* Copy debounced state and add battery pseudo-key */
- memcpy(state, keyboard_scan_get_state(), sizeof(state));
- state[BATTERY_KEY_COL] ^= BATTERY_KEY_ROW_MASK;
-
- /* Add to FIFO only if AP is on or else it will wake from suspend */
- if (chipset_in_state(CHIPSET_STATE_ON))
- mkbp_keyboard_add(state);
-}
-
-void clear_typematic_key(void)
-{ }
-
-static void set_keyscan_config(const struct ec_mkbp_config *src,
- struct ec_mkbp_protocol_config *dst,
- uint32_t valid_mask, uint8_t new_flags)
-{
- struct keyboard_scan_config *ksc = keyboard_scan_get_config();
-
- if (valid_mask & EC_MKBP_VALID_SCAN_PERIOD)
- ksc->scan_period_us = src->scan_period_us;
-
- if (valid_mask & EC_MKBP_VALID_POLL_TIMEOUT)
- ksc->poll_timeout_us = src->poll_timeout_us;
-
- if (valid_mask & EC_MKBP_VALID_MIN_POST_SCAN_DELAY) {
- /*
- * Key scanning is high priority, so we should require at
- * least 100us min delay here. Setting this to 0 will cause
- * watchdog events. Use 200 to be safe.
- */
- ksc->min_post_scan_delay_us =
- MAX(src->min_post_scan_delay_us, 200);
- }
-
- if (valid_mask & EC_MKBP_VALID_OUTPUT_SETTLE)
- ksc->output_settle_us = src->output_settle_us;
-
- if (valid_mask & EC_MKBP_VALID_DEBOUNCE_DOWN)
- ksc->debounce_down_us = src->debounce_down_us;
-
- if (valid_mask & EC_MKBP_VALID_DEBOUNCE_UP)
- ksc->debounce_up_us = src->debounce_up_us;
-
- /*
- * If we just enabled key scanning, kick the task so that it will
- * fall out of the task_wait_event() in keyboard_scan_task().
- */
- if ((new_flags & EC_MKBP_FLAGS_ENABLE) &&
- !(dst->flags & EC_MKBP_FLAGS_ENABLE))
- task_wake(TASK_ID_KEYSCAN);
-}
-
-static void get_keyscan_config(struct ec_mkbp_config *dst)
-{
- const struct keyboard_scan_config *ksc = keyboard_scan_get_config();
-
- /* Copy fields from keyscan config to mkbp config */
- dst->output_settle_us = ksc->output_settle_us;
- dst->debounce_down_us = ksc->debounce_down_us;
- dst->debounce_up_us = ksc->debounce_up_us;
- dst->scan_period_us = ksc->scan_period_us;
- dst->min_post_scan_delay_us = ksc->min_post_scan_delay_us;
- dst->poll_timeout_us = ksc->poll_timeout_us;
-}
-
-/**
- * Copy keyscan configuration from one place to another according to flags
- *
- * This is like a structure copy, except that only selected fields are
- * copied.
- *
- * @param src Source config
- * @param dst Destination config
- * @param valid_mask Bits representing which fields to copy - each bit is
- * from enum mkbp_config_valid
- * @param valid_flags Bit mask controlling flags to copy. Any 1 bit means
- * that the corresponding bit in src->flags is copied
- * over to dst->flags
- */
-static void keyscan_copy_config(const struct ec_mkbp_config *src,
- struct ec_mkbp_protocol_config *dst,
- uint32_t valid_mask, uint8_t valid_flags)
-{
- uint8_t new_flags;
-
- if (valid_mask & EC_MKBP_VALID_FIFO_MAX_DEPTH) {
- /* Validity check for fifo depth */
- dst->fifo_max_depth = MIN(src->fifo_max_depth,
- FIFO_DEPTH);
- }
-
- new_flags = dst->flags & ~valid_flags;
- new_flags |= src->flags & valid_flags;
-
- set_keyscan_config(src, dst, valid_mask, new_flags);
- dst->flags = new_flags;
-}
-
-static enum ec_status
-host_command_mkbp_set_config(struct host_cmd_handler_args *args)
-{
- const struct ec_params_mkbp_set_config *req = args->params;
-
- keyscan_copy_config(&req->config, &config,
- config.valid_mask & req->config.valid_mask,
- config.valid_flags & req->config.valid_flags);
-
- mkbp_fifo_depth_update(config.fifo_max_depth);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_MKBP_SET_CONFIG,
- host_command_mkbp_set_config,
- EC_VER_MASK(0));
-
-static enum ec_status
-host_command_mkbp_get_config(struct host_cmd_handler_args *args)
-{
- struct ec_response_mkbp_get_config *resp = args->response;
- struct ec_mkbp_config *dst = &resp->config;
-
- memcpy(&resp->config, &config, sizeof(config));
-
- /* Copy fields from mkbp protocol config to mkbp config */
- dst->valid_mask = config.valid_mask;
- dst->flags = config.flags;
- dst->valid_flags = config.valid_flags;
- dst->fifo_max_depth = config.fifo_max_depth;
-
- get_keyscan_config(dst);
-
- args->response_size = sizeof(*resp);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_MKBP_GET_CONFIG,
- host_command_mkbp_get_config,
- EC_VER_MASK(0));
diff --git a/common/keyboard_scan.c b/common/keyboard_scan.c
deleted file mode 100644
index 6584a55d84..0000000000
--- a/common/keyboard_scan.c
+++ /dev/null
@@ -1,1094 +0,0 @@
-/* Copyright 2013 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.
- */
-
-/* Keyboard scanner module for Chrome EC */
-
-#include "chipset.h"
-#include "clock.h"
-#include "common.h"
-#include "console.h"
-#include "ec_commands.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "keyboard_config.h"
-#include "keyboard_protocol.h"
-#include "keyboard_raw.h"
-#include "keyboard_scan.h"
-#include "keyboard_test.h"
-#include "lid_switch.h"
-#include "switch.h"
-#include "system.h"
-#include "tablet_mode.h"
-#include "task.h"
-#include "timer.h"
-#include "usb_api.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_KEYSCAN, outstr)
-#define CPRINTF(format, args...) cprintf(CC_KEYSCAN, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_KEYSCAN, format, ## args)
-
-#ifdef CONFIG_KEYBOARD_DEBUG
-#define CPUTS5(outstr) cputs(CC_KEYSCAN, outstr)
-#define CPRINTS5(format, args...) cprints(CC_KEYBOARD, format, ## args)
-#else
-#define CPUTS5(outstr)
-#define CPRINTS5(format, args...)
-#endif
-
-#define SCAN_TIME_COUNT 32 /* Number of last scan times to track */
-
-/* If we're waiting for a scan to happen, we'll give it this long */
-#define SCAN_TASK_TIMEOUT_US (100 * MSEC)
-
-#ifndef CONFIG_KEYBOARD_POST_SCAN_CLOCKS
-/*
- * Default delay in clocks; this was experimentally determined to be long
- * enough to avoid watchdog warnings or I2C errors on a typical notebook
- * config on STM32.
- */
-#define CONFIG_KEYBOARD_POST_SCAN_CLOCKS 16000
-#endif
-
-__overridable struct keyboard_scan_config keyscan_config = {
-#ifdef CONFIG_KEYBOARD_COL2_INVERTED
- /*
- * CONFIG_KEYBOARD_COL2_INVERTED is defined for passing the column 2
- * to H1 which inverts the signal. The signal passing through H1
- * adds more delay. Need a larger delay value. Otherwise, pressing
- * Refresh key will also trigger T key, which is in the next scanning
- * column line. See http://b/156007029.
- */
- .output_settle_us = 80,
-#else
- .output_settle_us = 50,
-#endif /* CONFIG_KEYBOARD_COL2_INVERTED */
- .debounce_down_us = 9 * MSEC,
- .debounce_up_us = 30 * MSEC,
- .scan_period_us = 3 * MSEC,
- .min_post_scan_delay_us = 1000,
- .poll_timeout_us = 100 * MSEC,
- .actual_key_mask = {
- 0x1c, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff,
- 0xa4, 0xff, 0xfe, 0x55, 0xfa, 0xca /* full set */
- },
-};
-
-/* Boot key list. Must be in same order as enum boot_key. */
-struct boot_key_entry {
- uint8_t mask_index;
- uint8_t mask_value;
-};
-
-#ifdef CONFIG_KEYBOARD_BOOT_KEYS
-static const struct boot_key_entry boot_key_list[] = {
- {KEYBOARD_COL_ESC, KEYBOARD_MASK_ESC}, /* Esc */
- {KEYBOARD_COL_DOWN, KEYBOARD_MASK_DOWN}, /* Down-arrow */
- {KEYBOARD_COL_LEFT_SHIFT, KEYBOARD_MASK_LEFT_SHIFT}, /* Left-Shift */
-};
-static uint32_t boot_key_value = BOOT_KEY_NONE;
-#endif
-
-uint8_t keyboard_cols = KEYBOARD_COLS_MAX;
-
-/* Debounced key matrix */
-static uint8_t __bss_slow debounced_state[KEYBOARD_COLS_MAX];
-/* Mask of keys being debounced */
-static uint8_t __bss_slow debouncing[KEYBOARD_COLS_MAX];
-/* Keys simulated-pressed */
-static uint8_t __bss_slow simulated_key[KEYBOARD_COLS_MAX];
-#ifdef CONFIG_KEYBOARD_LANGUAGE_ID
-static uint8_t __bss_slow keyboard_id[KEYBOARD_IDS];
-#endif
-
-/* Times of last scans */
-static uint32_t __bss_slow scan_time[SCAN_TIME_COUNT];
-/* Current scan_time[] index */
-static int __bss_slow scan_time_index;
-
-/* Index into scan_time[] when each key started debouncing */
-static uint8_t __bss_slow scan_edge_index[KEYBOARD_COLS_MAX][KEYBOARD_ROWS];
-
-/* Minimum delay between keyboard scans based on current clock frequency */
-static uint32_t __bss_slow post_scan_clock_us;
-
-/*
- * Print all keyboard scan state changes? Off by default because it generates
- * a lot of debug output, which makes the saved EC console data less useful.
- */
-static int __bss_slow print_state_changes;
-
-/* Must init to 0 for scanning at boot */
-static volatile uint32_t __bss_slow disable_scanning_mask;
-
-/* Constantly incrementing counter of the number of times we polled */
-static volatile int kbd_polls;
-
-/* If true, we'll force a keyboard poll */
-static volatile int force_poll;
-
-static int keyboard_scan_is_enabled(void)
-{
- /* NOTE: this is just an instantaneous glimpse of the variable. */
- return !disable_scanning_mask;
-}
-
-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);
- } else {
- atomic_or((uint32_t *)&disable_scanning_mask, mask);
- clear_typematic_key();
- }
-
- /* Let the task figure things out */
- task_wake(TASK_ID_KEYSCAN);
-}
-
-/**
- * Print the keyboard state.
- *
- * @param state State array to print
- * @param msg Description of state
- */
-static void print_state(const uint8_t *state, const char *msg)
-{
- int c;
-
- CPRINTF("[%pT KB %s:", PRINTF_TIMESTAMP_NOW, msg);
- for (c = 0; c < keyboard_cols; c++) {
- if (state[c])
- CPRINTF(" %02x", state[c]);
- else
- CPUTS(" --");
- }
- CPUTS("]\n");
-}
-
-/**
- * Ensure that the keyboard has been scanned.
- *
- * Makes sure that we've fully gone through the keyboard scanning loop at
- * least once.
- */
-static void ensure_keyboard_scanned(int old_polls)
-{
- uint64_t start_time;
-
- start_time = get_time().val;
-
- /*
- * Ensure we see the poll task run.
- *
- * Note that the poll task is higher priority than ours so we know that
- * while we're running it's not partway through a poll. That means that
- * if kbd_polls changes we've gone through a whole cycle.
- */
- while ((kbd_polls == old_polls) &&
- (get_time().val - start_time < SCAN_TASK_TIMEOUT_US))
- usleep(keyscan_config.scan_period_us);
-}
-
-/**
- * Simulate a keypress.
- *
- * @param row Row of key
- * @param col Column of key
- * @param pressed Non-zero if pressed, zero if released
- */
-static void simulate_key(int row, int col, int pressed)
-{
- int old_polls;
-
- if ((simulated_key[col] & BIT(row)) == ((pressed ? 1 : 0) << row))
- return; /* No change */
-
- simulated_key[col] ^= BIT(row);
-
- /* Keep track of polls now that we've got keys simulated */
- old_polls = kbd_polls;
-
- print_state(simulated_key, "simulated ");
-
- /* Force a poll even though no keys are pressed */
- force_poll = 1;
-
- /* Wake the task to handle changes in simulated keys */
- task_wake(TASK_ID_KEYSCAN);
-
- /*
- * Make sure that the keyboard task sees the key for long enough.
- * That means it needs to have run and for enough time.
- */
- ensure_keyboard_scanned(old_polls);
- usleep(pressed ?
- keyscan_config.debounce_down_us : keyscan_config.debounce_up_us);
- ensure_keyboard_scanned(kbd_polls);
-}
-
-/**
- * Read the raw keyboard matrix state.
- *
- * Used in pre-init, so must not make task-switching-dependent calls; udelay()
- * is ok because it's a spin-loop.
- *
- * @param state Destination for new state (must be KEYBOARD_COLS_MAX
- * long).
- *
- * @return 1 if at least one key is pressed, else zero.
- */
-static int read_matrix(uint8_t *state)
-{
- int c;
- int pressed = 0;
-
- /* 1. Read input pins */
- for (c = 0; c < keyboard_cols; c++) {
- /*
- * Skip if scanning becomes disabled. Clear the state
- * to make sure we don't mix new and old states in the
- * same array.
- *
- * Note, scanning is enabled on boot by default.
- */
- if (!keyboard_scan_is_enabled()) {
- state[c] = 0;
- continue;
- }
-
- /* Select column, then wait a bit for it to settle */
- keyboard_raw_drive_column(c);
- udelay(keyscan_config.output_settle_us);
-
- /* Read the row state */
- state[c] = keyboard_raw_read_rows();
-
- /* Use simulated keyscan sequence instead if testing active */
- if (IS_ENABLED(CONFIG_KEYBOARD_TEST))
- state[c] = keyscan_seq_get_scan(c, state[c]);
- }
-
- /* 2. Detect transitional ghost */
- for (c = 0; c < keyboard_cols; c++) {
- int c2;
-
- for (c2 = 0; c2 < c; c2++) {
- /*
- * If two columns shares at least one key but their
- * states are different, maybe the state changed between
- * two "keyboard_raw_read_rows"s. If this happened,
- * update both columns to the union of them.
- *
- * Note that in theory we need to rescan from col 0 if
- * anything is updated, to make sure the newly added
- * bits does not introduce more inconsistency.
- * Let's ignore this rare case for now.
- */
- if ((state[c] & state[c2]) && (state[c] != state[c2])) {
- uint8_t merged = state[c] | state[c2];
-
- state[c] = state[c2] = merged;
- }
- }
- }
-
- /* 3. Fix result */
- for (c = 0; c < keyboard_cols; c++) {
- /* Add in simulated keypresses */
- state[c] |= simulated_key[c];
-
- /*
- * Keep track of what keys appear to be pressed. Even if they
- * don't exist in the matrix, they'll keep triggering
- * interrupts, so we can't leave scanning mode.
- */
- pressed |= state[c];
-
- /* Mask off keys that don't exist on the actual keyboard */
- state[c] &= keyscan_config.actual_key_mask[c];
-
- }
-
- keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE);
-
- return pressed ? 1 : 0;
-}
-
-#ifdef CONFIG_KEYBOARD_LANGUAGE_ID
-/**
- * Read the raw keyboard IDs state.
- *
- * Used in pre-init, so must not make task-switching-dependent calls; udelay()
- * is ok because it's a spin-loop.
- *
- * @param id Destination for keyboard id (must be KEYBOARD_IDS long).
- *
- */
-static void read_matrix_id(uint8_t *id)
-{
- int c;
-
- for (c = 0; c < KEYBOARD_IDS; c++) {
- /* Select the ID pin, then wait a bit for it to settle.
- * Caveat: If a keyboard maker puts ID pins right after scan
- * columns, we can't support variable column size with a single
- * image. */
- keyboard_raw_drive_column(KEYBOARD_COLS_MAX + c);
- udelay(keyscan_config.output_settle_us);
-
- /* Read the row state */
- id[c] = keyboard_raw_read_rows();
-
- CPRINTS("Keyboard ID%u: 0x%02x", c, id[c]);
- }
-
- keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE);
-}
-#endif
-
-#ifdef CONFIG_KEYBOARD_RUNTIME_KEYS
-
-static uint8_t key_vol_up_row = KEYBOARD_DEFAULT_ROW_VOL_UP;
-static uint8_t key_vol_up_col = KEYBOARD_DEFAULT_COL_VOL_UP;
-
-void set_vol_up_key(uint8_t row, uint8_t col)
-{
- if (col < KEYBOARD_COLS_MAX && row < KEYBOARD_ROWS) {
- key_vol_up_row = row;
- key_vol_up_col = col;
- }
-}
-
-/**
- * Check special runtime key combinations.
- *
- * @param state Keyboard state to use when checking keys.
- *
- * @return 1 if a special key was pressed, 0 if not
- */
-static int check_runtime_keys(const uint8_t *state)
-{
- int num_press = 0;
- int c;
-
- /*
- * All runtime key combos are (right or left ) alt + volume up + (some
- * key NOT on the same col as alt or volume up )
- */
- if (state[key_vol_up_col] != KEYBOARD_ROW_TO_MASK(key_vol_up_row))
- return 0;
-
- if (state[KEYBOARD_COL_RIGHT_ALT] != KEYBOARD_MASK_RIGHT_ALT &&
- state[KEYBOARD_COL_LEFT_ALT] != KEYBOARD_MASK_LEFT_ALT)
- return 0;
-
- /*
- * Count number of columns with keys pressed. We know two columns are
- * pressed for volume up and alt, so if only one more key is pressed
- * there will be exactly 3 non-zero columns.
- */
- for (c = 0; c < keyboard_cols; c++) {
- if (state[c])
- num_press++;
- }
-
- if (num_press != 3)
- return 0;
-
- /* Check individual keys */
- if (state[KEYBOARD_COL_KEY_R] == KEYBOARD_MASK_KEY_R) {
- /* R = reboot */
- CPRINTS("KB warm reboot");
- keyboard_clear_buffer();
- chipset_reset(CHIPSET_RESET_KB_WARM_REBOOT);
- return 1;
- } else if (state[KEYBOARD_COL_KEY_H] == KEYBOARD_MASK_KEY_H) {
- /* H = hibernate */
- CPRINTS("KB hibernate");
- system_enter_hibernate(0, 0);
- return 1;
- }
-
- return 0;
-}
-#endif /* CONFIG_KEYBOARD_RUNTIME_KEYS */
-
-/**
- * Check for ghosting in the keyboard state.
- *
- * Assumes that the state has already been masked with the actual key mask, so
- * that coords which don't correspond with actual keys don't trigger ghosting
- * detection.
- *
- * @param state Keyboard state to check.
- *
- * @return 1 if ghosting detected, else 0.
- */
-static int has_ghosting(const uint8_t *state)
-{
- int c, c2;
-
- for (c = 0; c < keyboard_cols; c++) {
- if (!state[c])
- continue;
-
- for (c2 = c + 1; c2 < keyboard_cols; c2++) {
- /*
- * A little bit of cleverness here. Ghosting happens
- * if 2 columns share at least 2 keys. So we OR the
- * columns together and then see if more than one bit
- * is set. x&(x-1) is non-zero only if x has more than
- * one bit set.
- */
- uint8_t common = state[c] & state[c2];
-
- if (common & (common - 1))
- return 1;
- }
- }
-
- return 0;
-}
-
-/* Inform keyboard module if scanning is enabled */
-static void key_state_changed(int row, int col, uint8_t state)
-{
- if (!keyboard_scan_is_enabled())
- return;
-
- /* No-op for protocols that require full keyboard matrix (e.g. MKBP). */
- keyboard_state_changed(row, col, !!(state & BIT(row)));
-}
-
-/**
- * Update keyboard state using low-level interface to read keyboard.
- *
- * @param state Keyboard state to update.
- *
- * @return 1 if any key is still pressed, 0 if no key is pressed.
- */
-static int check_keys_changed(uint8_t *state)
-{
- int any_pressed = 0;
- int c, i;
- int any_change = 0;
- static uint8_t __bss_slow new_state[KEYBOARD_COLS_MAX];
- uint32_t tnow = get_time().le.lo;
-
- /* Save the current scan time */
- if (++scan_time_index >= SCAN_TIME_COUNT)
- scan_time_index = 0;
- scan_time[scan_time_index] = tnow;
-
- /* Read the raw key state */
- any_pressed = read_matrix(new_state);
-
- /* Ignore if so many keys are pressed that we're ghosting. */
- if (has_ghosting(new_state))
- return any_pressed;
-
- /* Check for changes between previous scan and this one */
- for (c = 0; c < keyboard_cols; c++) {
- int diff = new_state[c] ^ state[c];
-
- /* Clear debouncing flag, if sufficient time has elapsed. */
- for (i = 0; i < KEYBOARD_ROWS && debouncing[c]; i++) {
- if (!(debouncing[c] & BIT(i)))
- continue;
- if (tnow - scan_time[scan_edge_index[c][i]] <
- (state[c] ? keyscan_config.debounce_down_us :
- keyscan_config.debounce_up_us))
- continue; /* Not done debouncing */
- debouncing[c] &= ~BIT(i);
-
- if (!IS_ENABLED(CONFIG_KEYBOARD_STRICT_DEBOUNCE))
- continue;
- if (!(diff & BIT(i)))
- /* Debounced but no difference. */
- continue;
- any_change = 1;
- key_state_changed(i, c, new_state[c]);
- /*
- * This makes state[c] == new_state[c] for row i.
- * Thus, when diff is calculated below, it won't
- * be asserted (for row i).
- */
- state[c] ^= diff & BIT(i);
- }
-
- /* Recognize change in state, unless debounce in effect. */
- diff = (new_state[c] ^ state[c]) & ~debouncing[c];
- if (!diff)
- continue;
- for (i = 0; i < KEYBOARD_ROWS; i++) {
- if (!(diff & BIT(i)))
- continue;
- scan_edge_index[c][i] = scan_time_index;
-
- if (!IS_ENABLED(CONFIG_KEYBOARD_STRICT_DEBOUNCE)) {
- any_change = 1;
- key_state_changed(i, c, new_state[c]);
- }
- }
-
- /* For any keyboard events just sent, turn on debouncing. */
- debouncing[c] |= diff;
- /*
- * Note: In order to "remember" what was last reported
- * (up or down), the state bits are only updated if the
- * edge was not suppressed due to debouncing.
- */
- if (!IS_ENABLED(CONFIG_KEYBOARD_STRICT_DEBOUNCE))
- state[c] ^= diff;
- }
-
- if (any_change) {
-
-#ifdef CONFIG_KEYBOARD_SUPPRESS_NOISE
- /* Suppress keyboard noise */
- keyboard_suppress_noise();
-#endif
-
- if (print_state_changes)
- print_state(state, "state");
-
-#ifdef CONFIG_KEYBOARD_PRINT_SCAN_TIMES
- /* Print delta times from now back to each previous scan */
- CPRINTF("[%pT kb deltaT", PRINTF_TIMESTAMP_NOW);
- for (i = 0; i < SCAN_TIME_COUNT; i++) {
- int tnew = scan_time[
- (SCAN_TIME_COUNT + scan_time_index - i) %
- SCAN_TIME_COUNT];
- CPRINTF(" %d", tnow - tnew);
- }
- CPRINTF("]\n");
-#endif
-
-#ifdef CONFIG_KEYBOARD_RUNTIME_KEYS
- /* Swallow special keys */
- if (check_runtime_keys(state))
- return 0;
-#endif
-
-#ifdef CONFIG_KEYBOARD_PROTOCOL_MKBP
- mkbp_keyboard_add(state);
-#endif
- }
-
- kbd_polls++;
-
- return any_pressed;
-}
-
-static uint8_t keyboard_mask_refresh;
-__overridable uint8_t board_keyboard_row_refresh(void)
-{
- if (IS_ENABLED(CONFIG_KEYBOARD_REFRESH_ROW3))
- return 3;
- else
- return 2;
-}
-
-#ifdef CONFIG_KEYBOARD_BOOT_KEYS
-/*
- * Returns mask of the boot keys that are pressed, with at most the keys used
- * for keyboard-controlled reset also pressed.
- */
-static uint32_t check_key_list(const uint8_t *state)
-{
- uint8_t curr_state[KEYBOARD_COLS_MAX];
- int c;
- uint32_t boot_key_mask = BOOT_KEY_NONE;
- const struct boot_key_entry *k;
-
- /* Make copy of current debounced state. */
- memcpy(curr_state, state, sizeof(curr_state));
-
-#ifdef KEYBOARD_MASK_PWRBTN
- /*
- * Check if KSI2 or KSI3 is asserted for all columns due to power
- * button hold, and ignore it if so.
- */
- for (c = 0; c < keyboard_cols; c++)
- if ((keyscan_config.actual_key_mask[c] & KEYBOARD_MASK_PWRBTN)
- && !(curr_state[c] & KEYBOARD_MASK_PWRBTN))
- break;
-
- if (c == keyboard_cols)
- for (c = 0; c < keyboard_cols; c++)
- curr_state[c] &= ~KEYBOARD_MASK_PWRBTN;
-#endif
-
- curr_state[KEYBOARD_COL_REFRESH] &= ~keyboard_mask_refresh;
-
- /* Update mask with all boot keys that were pressed. */
- k = boot_key_list;
- for (c = 0; c < ARRAY_SIZE(boot_key_list); c++, k++) {
- if (curr_state[k->mask_index] & k->mask_value) {
- boot_key_mask |= BIT(c);
- curr_state[k->mask_index] &= ~k->mask_value;
- }
- }
-
- /* If any other key was pressed, ignore all boot keys. */
- for (c = 0; c < keyboard_cols; c++) {
- if (curr_state[c])
- return BOOT_KEY_NONE;
- }
-
- CPRINTS("KB boot key mask %x", boot_key_mask);
- return boot_key_mask;
-}
-
-/**
- * Check what boot key is down, if any.
- *
- * @param state Keyboard state at boot.
- *
- * @return the key which is down, or BOOT_KEY_NONE if an unrecognized
- * key combination is down or this isn't the right type of boot to look at
- * boot keys.
- */
-static uint32_t check_boot_key(const uint8_t *state)
-{
- /*
- * If we jumped to this image, ignore boot keys. This prevents
- * re-triggering events in RW firmware that were already processed by
- * RO firmware.
- */
- if (system_jumped_late())
- return BOOT_KEY_NONE;
-
- /* If reset was not caused by reset pin, refresh must be held down */
- if (!(system_get_reset_flags() & EC_RESET_FLAG_RESET_PIN) &&
- !(state[KEYBOARD_COL_REFRESH] & keyboard_mask_refresh))
- return BOOT_KEY_NONE;
-
- return check_key_list(state);
-}
-#endif
-
-static void keyboard_freq_change(void)
-{
- post_scan_clock_us = (CONFIG_KEYBOARD_POST_SCAN_CLOCKS * 1000) /
- (clock_get_freq() / 1000);
-}
-DECLARE_HOOK(HOOK_FREQ_CHANGE, keyboard_freq_change, HOOK_PRIO_DEFAULT);
-
-/*****************************************************************************/
-/* Interface */
-
-struct keyboard_scan_config *keyboard_scan_get_config(void)
-{
- return &keyscan_config;
-}
-
-#ifdef CONFIG_KEYBOARD_BOOT_KEYS
-uint32_t keyboard_scan_get_boot_keys(void)
-{
- return boot_key_value;
-}
-#endif
-
-const uint8_t *keyboard_scan_get_state(void)
-{
- return debounced_state;
-}
-
-void keyboard_scan_init(void)
-{
- if (IS_ENABLED(CONFIG_KEYBOARD_STRICT_DEBOUNCE) &&
- keyscan_config.debounce_down_us != keyscan_config.debounce_up_us) {
- /*
- * Strict debouncer is prone to keypress reordering if debounce
- * durations for down and up are not equal. crbug.com/547131
- */
- CPRINTS("KB WARN: Debounce durations not equal");
- }
-
- /* Configure refresh key matrix */
- keyboard_mask_refresh = KEYBOARD_ROW_TO_MASK(
- board_keyboard_row_refresh());
-
- /* Configure GPIO */
- keyboard_raw_init();
-
- /* Tri-state the columns */
- keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE);
-
- /* Initialize raw state */
- read_matrix(debounced_state);
-
-#ifdef CONFIG_KEYBOARD_LANGUAGE_ID
- /* Check keyboard ID state */
- read_matrix_id(keyboard_id);
-#endif
-
-#ifdef CONFIG_KEYBOARD_BOOT_KEYS
- /* Check for keys held down at boot */
- boot_key_value = check_boot_key(debounced_state);
-
- /*
- * If any key other than Esc or Left_Shift was pressed, do not trigger
- * recovery.
- */
- if (boot_key_value & ~(BOOT_KEY_ESC | BOOT_KEY_LEFT_SHIFT))
- return;
-
-#ifdef CONFIG_HOSTCMD_EVENTS
- if (boot_key_value & BOOT_KEY_ESC) {
- host_set_single_event(EC_HOST_EVENT_KEYBOARD_RECOVERY);
- /*
- * In recovery mode, we should force clamshell mode in order to
- * prevent the keyboard from being disabled unintentionally due
- * to unstable accel readings.
- *
- * You get the same effect if motion sensors or a motion sense
- * task are disabled in RO.
- */
- if (IS_ENABLED(CONFIG_TABLET_MODE))
- tablet_disable();
- if (boot_key_value & BOOT_KEY_LEFT_SHIFT)
- host_set_single_event(
- EC_HOST_EVENT_KEYBOARD_RECOVERY_HW_REINIT);
- }
-#endif
-#endif /* CONFIG_KEYBOARD_BOOT_KEYS */
-}
-
-void keyboard_scan_task(void *u)
-{
- timestamp_t poll_deadline, start;
- int wait_time;
- uint32_t local_disable_scanning = 0;
-
- print_state(debounced_state, "init state");
-
- keyboard_raw_task_start();
-
- /* Set initial clock frequency-based minimum delay between scans */
- keyboard_freq_change();
-
- while (1) {
- /* Enable all outputs */
- CPRINTS5("KB wait");
-
- keyboard_raw_enable_interrupt(1);
-
- /* Wait for scanning enabled and key pressed. */
- while (1) {
- uint32_t new_disable_scanning;
-
- /* Read it once to get consistent glimpse */
- new_disable_scanning = disable_scanning_mask;
-
- if (local_disable_scanning != new_disable_scanning)
- CPRINTS("KB disable_scanning_mask changed: "
- "0x%08x", new_disable_scanning);
-
- if (!new_disable_scanning) {
- /* Enabled now */
- keyboard_raw_drive_column(KEYBOARD_COLUMN_ALL);
- } else if (!local_disable_scanning) {
- /*
- * Scanning isn't enabled but it was last time
- * we looked.
- *
- * No race here even though we're basing on a
- * glimpse of disable_scanning_mask since if
- * someone changes disable_scanning_mask they
- * are guaranteed to call task_wake() on us
- * afterward so we'll run the loop again.
- */
- keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE);
- keyboard_clear_buffer();
- }
-
- local_disable_scanning = new_disable_scanning;
-
- /*
- * Done waiting if scanning is enabled and a key is
- * already pressed. This prevents a race between the
- * user pressing a key and enable_interrupt()
- * starting to pay attention to edges.
- */
- if (!local_disable_scanning &&
- (keyboard_raw_read_rows() || force_poll))
- break;
- else
- task_wait_event(-1);
- }
-
- /* We're about to poll, so any existing forces are fulfilled */
- force_poll = 0;
-
- /* Enter polling mode */
- CPRINTS5("KB poll");
- keyboard_raw_enable_interrupt(0);
- keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE);
-
- /* Busy polling keyboard state. */
- while (keyboard_scan_is_enabled()) {
- start = get_time();
-
- /* Check for keys down */
- if (check_keys_changed(debounced_state)) {
- poll_deadline.val = start.val
- + keyscan_config.poll_timeout_us;
- } else if (timestamp_expired(poll_deadline, &start)) {
- break;
- }
-
- /* Delay between scans */
- wait_time = keyscan_config.scan_period_us -
- (get_time().val - start.val);
-
- if (wait_time < keyscan_config.min_post_scan_delay_us)
- wait_time =
- keyscan_config.min_post_scan_delay_us;
-
- if (wait_time < post_scan_clock_us)
- wait_time = post_scan_clock_us;
-
- usleep(wait_time);
- }
- }
-}
-
-#ifdef CONFIG_LID_SWITCH
-
-static void keyboard_lid_change(void)
-{
- if (lid_is_open())
- keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_CLOSED);
- else
- keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_CLOSED);
-}
-DECLARE_HOOK(HOOK_LID_CHANGE, keyboard_lid_change, HOOK_PRIO_DEFAULT);
-DECLARE_HOOK(HOOK_INIT, keyboard_lid_change, HOOK_PRIO_INIT_LID + 1);
-
-#endif
-
-#ifdef CONFIG_USB_SUSPEND
-static void keyboard_usb_pm_change(void)
-{
- /*
- * If USB interface is suspended, and host is not asking us to do remote
- * wakeup, we can turn off the key scanning.
- */
- if (usb_is_suspended() && !usb_is_remote_wakeup_enabled())
- keyboard_scan_enable(0, KB_SCAN_DISABLE_USB_SUSPENDED);
- else
- keyboard_scan_enable(1, KB_SCAN_DISABLE_USB_SUSPENDED);
-}
-DECLARE_HOOK(HOOK_USB_PM_CHANGE, keyboard_usb_pm_change, HOOK_PRIO_DEFAULT);
-#endif
-
-/*****************************************************************************/
-/* Host commands */
-
-static enum ec_status
-mkbp_command_simulate_key(struct host_cmd_handler_args *args)
-{
- const struct ec_params_mkbp_simulate_key *p = args->params;
-
- /* Only available on unlocked systems */
- if (system_is_locked())
- return EC_RES_ACCESS_DENIED;
-
- if (p->col >= keyboard_cols || p->row >= KEYBOARD_ROWS)
- return EC_RES_INVALID_PARAM;
-
- simulate_key(p->row, p->col, p->pressed);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_MKBP_SIMULATE_KEY,
- mkbp_command_simulate_key,
- EC_VER_MASK(0));
-
-#ifdef CONFIG_KEYBOARD_FACTORY_TEST
-
-/* Run keyboard factory testing, scan out KSO/KSI if any shorted. */
-int keyboard_factory_test_scan(void)
-{
- int i, j, flags;
- uint16_t shorted = 0;
- int port, id;
-
- /* Disable keyboard scan while testing */
- keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_CLOSED);
- flags = gpio_get_default_flags(GPIO_KBD_KSO2);
-
- /* Set all of KSO/KSI pins to internal pull-up and input */
- for (i = 0; i < keyboard_factory_scan_pins_used; i++) {
-
- if (keyboard_factory_scan_pins[i][0] < 0)
- continue;
-
- port = keyboard_factory_scan_pins[i][0];
- id = keyboard_factory_scan_pins[i][1];
-
- gpio_set_alternate_function(port, 1 << id,
- GPIO_ALT_FUNC_NONE);
- gpio_set_flags_by_mask(port, 1 << id,
- GPIO_INPUT | GPIO_PULL_UP);
- }
-
- /*
- * Set start pin to output low, then check other pins
- * going to low level, it indicate the two pins are shorted.
- */
- for (i = 0; i < keyboard_factory_scan_pins_used; i++) {
-
- if (keyboard_factory_scan_pins[i][0] < 0)
- continue;
-
- port = keyboard_factory_scan_pins[i][0];
- id = keyboard_factory_scan_pins[i][1];
-
- gpio_set_flags_by_mask(port, 1 << id, GPIO_OUT_LOW);
-
- for (j = 0; j < i; j++) {
-
- if (keyboard_factory_scan_pins[j][0] < 0)
- continue;
-
- if (keyboard_raw_is_input_low(
- keyboard_factory_scan_pins[j][0],
- keyboard_factory_scan_pins[j][1])) {
- shorted = i << 8 | j;
- goto done;
- }
- }
- gpio_set_flags_by_mask(port, 1 << id,
- GPIO_INPUT | GPIO_PULL_UP);
- }
-done:
- gpio_config_module(MODULE_KEYBOARD_SCAN, 1);
- gpio_set_flags(GPIO_KBD_KSO2, flags);
- keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_CLOSED);
-
- return shorted;
-}
-
-static enum ec_status keyboard_factory_test(struct host_cmd_handler_args *args)
-{
- struct ec_response_keyboard_factory_test *r = args->response;
-
- /* Only available on unlocked systems */
- if (system_is_locked())
- return EC_RES_ACCESS_DENIED;
-
- if (keyboard_factory_scan_pins_used == 0)
- return EC_RES_INVALID_COMMAND;
-
- r->shorted = keyboard_factory_test_scan();
-
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-
-DECLARE_HOST_COMMAND(EC_CMD_KEYBOARD_FACTORY_TEST,
- keyboard_factory_test,
- EC_VER_MASK(0));
-#endif
-
-#ifdef CONFIG_KEYBOARD_LANGUAGE_ID
-int keyboard_get_keyboard_id(void)
-{
- int c;
- uint32_t id = 0;
-
- BUILD_ASSERT(sizeof(id) >= KEYBOARD_IDS);
-
- for (c = 0; c < KEYBOARD_IDS; c++) {
- /* Check ID ghosting if more than one bit in any KSIs was set */
- if (keyboard_id[c] & (keyboard_id[c] - 1))
- /* ID ghosting is found */
- return KEYBOARD_ID_UNREADABLE;
- else
- id |= keyboard_id[c] << (c * 8);
- }
- return id;
-}
-#endif
-
-/*****************************************************************************/
-/* Console commands */
-#ifdef CONFIG_CMD_KEYBOARD
-static int command_ksstate(int argc, char **argv)
-{
- if (argc > 1) {
- if (!strcasecmp(argv[1], "force")) {
- print_state_changes = 1;
- keyboard_scan_enable(1, -1);
- } else if (!parse_bool(argv[1], &print_state_changes)) {
- return EC_ERROR_PARAM1;
- }
- }
-
- print_state(debounced_state, "debounced ");
- print_state(debouncing, "debouncing");
-
- ccprintf("Keyboard scan disable mask: 0x%08x\n",
- disable_scanning_mask);
- ccprintf("Keyboard scan state printing %s\n",
- print_state_changes ? "on" : "off");
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(ksstate, command_ksstate,
- "ksstate [on | off | force]",
- "Show or toggle printing keyboard scan state");
-
-static int command_keyboard_press(int argc, char **argv)
-{
- if (argc == 1) {
- int i, j;
-
- ccputs("Simulated keys:\n");
- for (i = 0; i < keyboard_cols; ++i) {
- if (simulated_key[i] == 0)
- continue;
- for (j = 0; j < KEYBOARD_ROWS; ++j)
- if (simulated_key[i] & BIT(j))
- ccprintf("\t%d %d\n", i, j);
- }
-
- } else if (argc == 3 || argc == 4) {
- int r, c, p;
- char *e;
-
- c = strtoi(argv[1], &e, 0);
- if (*e || c < 0 || c >= keyboard_cols)
- return EC_ERROR_PARAM1;
-
- r = strtoi(argv[2], &e, 0);
- if (*e || r < 0 || r >= KEYBOARD_ROWS)
- return EC_ERROR_PARAM2;
-
- if (argc == 3) {
- /* Simulate a press and release */
- simulate_key(r, c, 1);
- simulate_key(r, c, 0);
- } else {
- p = strtoi(argv[3], &e, 0);
- if (*e || p < 0 || p > 1)
- return EC_ERROR_PARAM3;
-
- simulate_key(r, c, p);
- }
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(kbpress, command_keyboard_press,
- "[col row [0 | 1]]",
- "Simulate keypress");
-#endif
diff --git a/common/keyboard_test.c b/common/keyboard_test.c
deleted file mode 100644
index e7b1dfe501..0000000000
--- a/common/keyboard_test.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-#include <common.h>
-#include <console.h>
-#include <ec_commands.h>
-#include <host_command.h>
-#include <keyboard_test.h>
-#include <task.h>
-#include <util.h>
-
-enum {
- KEYSCAN_MAX_LENGTH = 20,
- KEYSCAN_SEQ_START_DELAY_US = 10000,
-};
-
-static uint8_t keyscan_seq_count;
-static int8_t keyscan_seq_upto = -1;
-static struct keyscan_item keyscan_items[KEYSCAN_MAX_LENGTH];
-struct keyscan_item *keyscan_seq_cur;
-
-static int keyscan_seq_is_active(void)
-{
- return keyscan_seq_upto != -1;
-}
-
-/**
- * Get the current item in the keyscan sequence
- *
- * This looks at the current time, and returns the correct key scan for that
- * time.
- *
- * @return pointer to keyscan item, or NULL if none
- */
-static const struct keyscan_item *keyscan_seq_get(void)
-{
- struct keyscan_item *ksi;
-
- if (!keyscan_seq_is_active())
- return NULL;
-
- ksi = &keyscan_items[keyscan_seq_upto];
- while (keyscan_seq_upto < keyscan_seq_count) {
- /*
- * If we haven't reached the time for the next one, return
- * this one.
- */
- if (!timestamp_expired(ksi->abs_time, NULL)) {
- /* Yippee, we get to present this one! */
- if (keyscan_seq_cur)
- keyscan_seq_cur->done = 1;
- return keyscan_seq_cur;
- }
-
- keyscan_seq_cur = ksi;
- keyscan_seq_upto++;
- ksi++;
- }
-
- ccprints("keyscan_seq done, upto=%d", keyscan_seq_upto);
- keyscan_seq_upto = -1;
- keyscan_seq_cur = NULL;
- return NULL;
-}
-
-uint8_t keyscan_seq_get_scan(int column, uint8_t scan)
-{
- const struct keyscan_item *item;
-
- /* Use simulated keyscan sequence instead if active */
- item = keyscan_seq_get();
- if (item) {
- /* OR all columns together */
- if (column == -1) {
- int c;
-
- scan = 0;
- for (c = 0; c < keyboard_cols; c++)
- scan |= item->scan[c];
- } else {
- scan = item->scan[column];
- }
- }
-
- return scan;
-}
-
-int keyscan_seq_next_event_delay(void)
-{
- const struct keyscan_item *ksi;
- int delay;
-
- /*
- * Make sure we are pointing to the right event. This function will
- * return the event that should currently be presented. In fact we
- * want to look at the next event to be presented, so we manually
- * look that up after calling this function.
- */
- ksi = keyscan_seq_get();
-
- if (!keyscan_seq_is_active())
- return -1;
-
- /* Calculate the delay until the event */
- ksi = &keyscan_items[keyscan_seq_upto];
- delay = MAX(ksi->abs_time.val - get_time().val, 0);
-
- return delay;
-}
-
-static void keyscan_seq_start(void)
-{
- timestamp_t start;
- int i;
-
- start = get_time();
- start.val += KEYSCAN_SEQ_START_DELAY_US;
- for (i = 0; i < keyscan_seq_count; i++) {
- struct keyscan_item *ksi = &keyscan_items[i];
-
- ksi->abs_time = start;
- ksi->abs_time.val += ksi->time_us;
- }
-
- keyscan_seq_upto = 0;
- keyscan_seq_cur = NULL;
- task_wake(TASK_ID_KEYSCAN);
-}
-
-static int keyscan_seq_collect(struct ec_params_keyscan_seq_ctrl *req,
- struct ec_result_keyscan_seq_ctrl *resp)
-{
- struct keyscan_item *ksi;
- int start, end;
- int i;
-
- /* Range check the input values */
- start = req->collect.start_item;
- end = start + req->collect.num_items;
- if (start >= keyscan_seq_count)
- end = start;
- else
- end = MIN(end, keyscan_seq_count);
- start = MIN(start, end);
-
- /* Response plus one byte per item */
- end = MIN(end - start, EC_HOST_PARAM_SIZE - sizeof(*resp));
- resp->collect.num_items = end - start;
-
- for (i = start, ksi = keyscan_items; i < end; i++, ksi++)
- resp->collect.item[i].flags = ksi->done ?
- EC_KEYSCAN_SEQ_FLAG_DONE : 0;
-
- return sizeof(*resp) + resp->collect.num_items;
-}
-
-static enum ec_status keyscan_seq_ctrl(struct host_cmd_handler_args *args)
-{
- struct ec_params_keyscan_seq_ctrl req, *msg;
- struct keyscan_item *ksi;
-
- /* For now we must do our own alignment */
- memcpy(&req, args->params, sizeof(req));
-
- ccprintf("keyscan %d\n", req.cmd);
- switch (req.cmd) {
- case EC_KEYSCAN_SEQ_CLEAR:
- keyscan_seq_count = 0;
- break;
- case EC_KEYSCAN_SEQ_ADD:
- if (keyscan_seq_count == KEYSCAN_MAX_LENGTH)
- return EC_RES_OVERFLOW;
-
- ksi = &keyscan_items[keyscan_seq_count];
- ksi->time_us = req.add.time_us;
- ksi->done = 0;
- ksi->abs_time.val = 0;
- msg = (struct ec_params_keyscan_seq_ctrl *)args->params;
- memcpy(ksi->scan, msg->add.scan, sizeof(ksi->scan));
- keyscan_seq_count++;
- break;
- case EC_KEYSCAN_SEQ_START:
- keyscan_seq_start();
- break;
- case EC_KEYSCAN_SEQ_COLLECT:
- args->response_size = keyscan_seq_collect(&req,
- (struct ec_result_keyscan_seq_ctrl *)args->response);
- break;
- default:
- return EC_RES_INVALID_COMMAND;
- }
-
- return EC_RES_SUCCESS;
-}
-
-DECLARE_HOST_COMMAND(EC_CMD_KEYSCAN_SEQ_CTRL,
- keyscan_seq_ctrl,
- EC_VER_MASK(0));
diff --git a/common/keyboard_vivaldi.c b/common/keyboard_vivaldi.c
deleted file mode 100644
index 443b475c82..0000000000
--- a/common/keyboard_vivaldi.c
+++ /dev/null
@@ -1,187 +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.
- */
-
-/* Vivali Keyboard code for Chrome EC */
-
-#include "keyboard_8042_sharedlib.h"
-#include "keyboard_scan.h"
-#include "ec_commands.h"
-#include <host_command.h>
-#include <util.h>
-#include <hooks.h>
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_KEYBOARD, outstr)
-#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args)
-
-/*
- * Row Column info for Top row keys T1 - T15. This has been sourced from
- * go/vivaldi-matrix (internal link for vivaldi scan matrix spec).
- */
-static const struct key {
- uint8_t row;
- uint8_t col;
-} vivaldi_keys[] = {
- {.row = 0, .col = 2}, /* T1 */
- {.row = 3, .col = 2}, /* T2 */
- {.row = 2, .col = 2}, /* T3 */
- {.row = 1, .col = 2}, /* T4 */
- {.row = 3, .col = 4}, /* T5 */
- {.row = 2, .col = 4}, /* T6 */
- {.row = 1, .col = 4}, /* T7 */
- {.row = 2, .col = 9}, /* T8 */
- {.row = 1, .col = 9}, /* T9 */
- {.row = 0, .col = 4}, /* T10 */
- {.row = 0, .col = 1}, /* T11 */
- {.row = 1, .col = 5}, /* T12 */
- {.row = 3, .col = 5}, /* T13 */
- {.row = 0, .col = 9}, /* T14 */
- {.row = 0, .col = 11}, /* T15 */
-};
-BUILD_ASSERT(ARRAY_SIZE(vivaldi_keys) == MAX_TOP_ROW_KEYS);
-
-/* Scancodes for top row action keys */
-static const uint16_t action_scancodes[] = {
- [TK_BACK] = SCANCODE_BACK,
- [TK_FORWARD] = SCANCODE_FORWARD,
- [TK_REFRESH] = SCANCODE_REFRESH,
- [TK_FULLSCREEN] = SCANCODE_FULLSCREEN,
- [TK_OVERVIEW] = SCANCODE_OVERVIEW,
- [TK_VOL_MUTE] = SCANCODE_VOLUME_MUTE,
- [TK_VOL_DOWN] = SCANCODE_VOLUME_DOWN,
- [TK_VOL_UP] = SCANCODE_VOLUME_UP,
- [TK_PLAY_PAUSE] = SCANCODE_PLAY_PAUSE,
- [TK_NEXT_TRACK] = SCANCODE_NEXT_TRACK,
- [TK_PREV_TRACK] = SCANCODE_PREV_TRACK,
- [TK_SNAPSHOT] = SCANCODE_SNAPSHOT,
- [TK_BRIGHTNESS_DOWN] = SCANCODE_BRIGHTNESS_DOWN,
- [TK_BRIGHTNESS_UP] = SCANCODE_BRIGHTNESS_UP,
- [TK_KBD_BKLIGHT_DOWN] = SCANCODE_KBD_BKLIGHT_DOWN,
- [TK_KBD_BKLIGHT_UP] = SCANCODE_KBD_BKLIGHT_UP,
- [TK_PRIVACY_SCRN_TOGGLE] = SCANCODE_PRIVACY_SCRN_TOGGLE,
- [TK_MICMUTE] = SCANCODE_MICMUTE,
- [TK_KBD_BKLIGHT_TOGGLE] = SCANCODE_KBD_BKLIGHT_TOGGLE,
-};
-
-static const struct ec_response_keybd_config *vivaldi_keybd;
-
-static enum
-ec_status get_vivaldi_keybd_config(struct host_cmd_handler_args *args)
-{
- struct ec_response_keybd_config *resp = args->response;
-
- if (vivaldi_keybd && vivaldi_keybd->num_top_row_keys) {
- memcpy(resp, vivaldi_keybd, sizeof(*resp));
- args->response_size = sizeof(*resp);
- return EC_RES_SUCCESS;
- }
- return EC_RES_ERROR;
-}
-DECLARE_HOST_COMMAND(EC_CMD_GET_KEYBD_CONFIG, get_vivaldi_keybd_config,
- EC_VER_MASK(0));
-
-#ifdef CONFIG_KEYBOARD_CUSTOMIZATION
-
-/*
- * Boards selecting CONFIG_KEYBOARD_CUSTOMIZATION are likely to not
- * want vivaldi code messing with their customized keyboards.
- */
-__overridable
-const struct ec_response_keybd_config *board_vivaldi_keybd_config(void)
-{
- return NULL;
-}
-
-#else
-
-static const struct ec_response_keybd_config default_keybd = {
- /* Default Chromeos keyboard config */
- .num_top_row_keys = 10,
- .action_keys = {
- TK_BACK, /* T1 */
- TK_FORWARD, /* T2 */
- TK_REFRESH, /* T3 */
- TK_FULLSCREEN, /* T4 */
- TK_OVERVIEW, /* T5 */
- TK_BRIGHTNESS_DOWN, /* T6 */
- TK_BRIGHTNESS_UP, /* T7 */
- TK_VOL_MUTE, /* T8 */
- TK_VOL_DOWN, /* T9 */
- TK_VOL_UP, /* T10 */
- },
- /* No function keys, no numeric keypad, has screenlock key */
- .capabilities = KEYBD_CAP_SCRNLOCK_KEY,
-};
-
-__overridable
-const struct ec_response_keybd_config *board_vivaldi_keybd_config(void)
-{
- return &default_keybd;
-}
-
-#endif /* CONFIG_KEYBOARD_CUSTOMIZATION */
-
-static void vivaldi_init(void)
-{
- uint8_t i;
-
- /* Allow the boards to change the keyboard config */
- vivaldi_keybd = board_vivaldi_keybd_config();
-
- if (!vivaldi_keybd || !vivaldi_keybd->num_top_row_keys) {
- CPUTS("VIVALDI keybd disabled on board request");
- return;
- }
-
- CPRINTS("VIVALDI: Num top row keys = %u",
- vivaldi_keybd->num_top_row_keys);
-
- if (vivaldi_keybd->num_top_row_keys > MAX_TOP_ROW_KEYS ||
- vivaldi_keybd->num_top_row_keys < MIN_TOP_ROW_KEYS) {
- CPRINTS("VIVALDI: Error! num_top_row_keys=%u, disabled vivaldi",
- vivaldi_keybd->num_top_row_keys);
- vivaldi_keybd = NULL;
- return;
- }
-
- for (i = 0; i < ARRAY_SIZE(vivaldi_keys); i++) {
-
- uint8_t row, col, *mask;
- enum action_key key;
-
- row = vivaldi_keys[i].row;
- col = vivaldi_keys[i].col;
-
- if (col >= KEYBOARD_COLS_MAX || row >= KEYBOARD_ROWS) {
- CPRINTS("VIVALDI: Bad (row,col) for T-%u: (%u,%u)",
- i, row, col);
- ASSERT(false);
- }
-
- mask = &keyscan_config.actual_key_mask[col];
-
- /*
- * Potentially indexing past meaningful data,
- * but we bounds check it below.
- */
- key = vivaldi_keybd->action_keys[i];
-
- if (i < vivaldi_keybd->num_top_row_keys && key != TK_ABSENT) {
-
- /* Enable the mask */
- *mask |= BIT(row);
-
- /* Populate the scancode */
- set_scancode_set2(row, col, action_scancodes[key]);
- CPRINTS("VIVALDI key-%u (r-%u, c-%u) = scancode-%X",
- i, row, col, action_scancodes[key]);
-
- if (key == TK_VOL_UP)
- set_vol_up_key(row, col);
-
- }
- }
-}
-DECLARE_HOOK(HOOK_INIT, vivaldi_init, HOOK_PRIO_DEFAULT);
diff --git a/common/lb_common.c b/common/lb_common.c
deleted file mode 100644
index 019e0e254f..0000000000
--- a/common/lb_common.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/* Copyright 2012 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.
- *
- * Lightbar IC interface
- *
- * Here's the API provided by this file.
- *
- * Looking at it from the outside, the lightbar has four "segments", each of
- * which can be independently adjusted to display a unique color such as blue,
- * purple, yellow, pinkish-white, etc. Segment 0 is on the left (looking
- * straight at it from behind).
- *
- * The lb_set_rgb() and lb_get_rgb() functions let you specify the color of a
- * segment using individual Red, Green, and Blue values in the 0x00 to 0xFF
- * range (see https://en.wikipedia.org/wiki/Web_color for background info).
- *
- * The lb_set_brightness() function provides a simple way to set the intensity,
- * over a range of 0x00 (off) to 0xFF (full brightness). It does this by
- * scaling each RGB value proportionally. For example, an RGB value of #FF8000
- * appears orange. To make the segment half as bright, you could specify a RGB
- * value of #7f4000, or you could leave the RGB value unchanged and just set
- * the brightness to 0x80.
- *
- * That covers most of the lb_* functions found in include/lb_common.h, and
- * those functions are what are used to implement the various colors and
- * sequences for displaying power state changes and other events.
- *
- * The internals are a little more messy.
- *
- * Each segment has three individual color emitters - red, green, and blue. A
- * single emitter may consist of 3 to 7 physical LEDs, but they are all wired
- * in parallel so there is only one wire that provides current for any one
- * color emitter. That makes a total of 12 current control wires for the
- * lightbar: four segments, three color emitters per segment.
- *
- * The ICs that we use each have seven independently adjustable
- * current-limiters. We use six of those current limiters (called "Independent
- * Sink Controls", or "ISC"s ) from each of two ICs to control the 12 color
- * emitters in the lightbar. The ICs are not identical, but they're close
- * enough that we can treat them the same. We call the ICs "controller 0" and
- * "controller 1".
- *
- * For no apparent reason, each Chromebook has wired the ICs and the ISCs
- * differently, so there are a couple of lookup tables that ensure that when we
- * call lb_set_rgb() to make segment 1 yellow, it looks the same on all
- * Chromebooks.
- *
- * Each ISC has a control register to set the amount of current that passes
- * through the color emitter control wire. We need to limit the max current so
- * that the current through each of the emitter's LEDs doesn't exceed the
- * manufacturer's specifications. For example, if a particular LED can't handle
- * more than 5 mA, and the emitter is made up of four LEDs in parallel, the
- * maxiumum limit for that particular ISC would be 20 mA.
- *
- * Although the specified maximum currents are usually similar, the three
- * different colors of LEDs have different brightnesses. For any given current,
- * green LEDs are pretty bright, red LEDS are medium, and blue are fairly dim.
- * So we calibrate the max current per ISC differently, depending on which
- * color it controls.
- *
- * First we set one segment to red, one to green, and one to blue, using the
- * ISC register to allow the max current per LED that the LED manufacturer
- * recommends. Then we adjust the current of the brighter segments downward
- * until all three segments appear equally bright to the eye. The MAX_RED,
- * MAX_BLUE, and MAX_GREEN values are the ISC control register values at this
- * point. This means that if we set all ISCs to their MAX_* values, all
- * segments should appear white.
- *
- * To translate the RGB values passed to lb_set_rgb() into ISC values, we
- * perform two transformations. The color value is first scaled according to
- * the current brightness setting, and then that intensity is scaled according
- * to the MAX_* value for the particular color. The result is the ISC register
- * value to use.
- *
- * To add lightbar support for a new Chromebook, you do the following:
- *
- * 1. Figure out the segment-to-IC and color-to-ISC mappings so that
- * lb_set_rgb() does the same thing as on the other Chromebooks.
- *
- * 2. Calibrate the MAX_RED, MAX_GREEN, and MAX_BLUE values so that white looks
- * white, and solid red, green, and blue all appear to be the same
- * brightness.
- *
- * 3. Use lb_set_rgb() to set the colors to what *should be* the Google colors
- * (at maximum brightness). Tweak the RGB values until the colors match,
- * then edit common/lightbar.c to set them as the defaults.
- *
- * 4. Curse because the physical variation between the LEDs prevents you from
- * getting everything exactly right: white looks bluish, yellow turns
- * orange at lower brightness, segment 3 has a bright spot when displaying
- * solid red, etc. Go back to step 2, and repeat until deadline.
- */
-
-#include "common.h"
-#include "console.h"
-#include "ec_commands.h"
-#include "i2c.h"
-#include "lb_common.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_LIGHTBAR, outstr)
-#define CPRINTF(format, args...) cprintf(CC_LIGHTBAR, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_LIGHTBAR, format, ## args)
-
-/******************************************************************************/
-/* How to talk to the controller */
-/******************************************************************************/
-
-/* Since there's absolutely nothing we can do about it if an I2C access
- * isn't working, we're completely ignoring any failures. */
-
-static const uint16_t i2c_addr_flags[] = { 0x2A, 0x2B };
-
-static inline void controller_write(int ctrl_num, uint8_t reg, uint8_t val)
-{
- uint8_t buf[2];
-
- buf[0] = reg;
- buf[1] = val;
- ctrl_num = ctrl_num % ARRAY_SIZE(i2c_addr_flags);
- i2c_xfer_unlocked(I2C_PORT_LIGHTBAR, i2c_addr_flags[ctrl_num],
- buf, 2, 0, 0,
- I2C_XFER_SINGLE);
-}
-
-static inline uint8_t controller_read(int ctrl_num, uint8_t reg)
-{
- uint8_t buf[1];
- int rv;
-
- ctrl_num = ctrl_num % ARRAY_SIZE(i2c_addr_flags);
- rv = i2c_xfer_unlocked(I2C_PORT_LIGHTBAR, i2c_addr_flags[ctrl_num],
- &reg, 1, buf, 1, I2C_XFER_SINGLE);
- return rv ? 0 : buf[0];
-}
-
-/******************************************************************************/
-/* Controller details. We have an ADP8861 and and ADP8863, but we can treat
- * them identically for our purposes */
-/******************************************************************************/
-
-#ifdef BOARD_BDS
-/* We need to limit the total current per ISC to no more than 20mA (5mA per
- * color LED, but we have four LEDs in parallel on each ISC). Any more than
- * that runs the risk of damaging the LED component. A value of 0x67 is as high
- * as we want (assuming Square Law), but the blue LED is the least bright, so
- * I've lowered the other colors until they all appear approximately equal
- * brightness when full on. That's still pretty bright and a lot of current
- * drain on the battery, so we'll probably rarely go that high. */
-#define MAX_RED 0x5c
-#define MAX_GREEN 0x30
-#define MAX_BLUE 0x67
-#endif
-#ifdef BOARD_HOST
-/* For testing only */
-#define MAX_RED 0xff
-#define MAX_GREEN 0xff
-#define MAX_BLUE 0xff
-#endif
-
-/* How we'd like to see the driver chips initialized. The controllers have some
- * auto-cycling capability, but it's not much use for our purposes. For now,
- * we'll just control all color changes actively. */
-struct initdata_s {
- uint8_t reg;
- uint8_t val;
-};
-
-static const struct initdata_s init_vals[] = {
- {0x04, 0x00}, /* no backlight function */
- {0x05, 0x3f}, /* xRGBRGB per chip */
- {0x0f, 0x01}, /* square law looks better */
- {0x10, 0x3f}, /* enable independent LEDs */
- {0x11, 0x00}, /* no auto cycling */
- {0x12, 0x00}, /* no auto cycling */
- {0x13, 0x00}, /* instant fade in/out */
- {0x14, 0x00}, /* not using LED 7 */
- {0x15, 0x00}, /* current for LED 6 (blue) */
- {0x16, 0x00}, /* current for LED 5 (red) */
- {0x17, 0x00}, /* current for LED 4 (green) */
- {0x18, 0x00}, /* current for LED 3 (blue) */
- {0x19, 0x00}, /* current for LED 2 (red) */
- {0x1a, 0x00}, /* current for LED 1 (green) */
-};
-
-/* Controller register lookup tables. */
-static const uint8_t led_to_ctrl[] = { 1, 1, 0, 0 };
-#ifdef BOARD_BDS
-static const uint8_t led_to_isc[] = { 0x18, 0x15, 0x18, 0x15 };
-#endif
-#ifdef BOARD_HOST
-/* For testing only */
-static const uint8_t led_to_isc[] = { 0x15, 0x18, 0x15, 0x18 };
-#endif
-
-/* Scale 0-255 into max value */
-static inline uint8_t scale_abs(int val, int max)
-{
- return (val * max)/255;
-}
-
-/* This is the overall brightness control. */
-static int brightness = 0xc0;
-
-/* So that we can make brightness changes happen instantly, we need to track
- * the current values. The values in the controllers aren't very helpful. */
-static uint8_t current[NUM_LEDS][3];
-
-/* Scale 0-255 by brightness */
-static inline uint8_t scale(int val, int max)
-{
- return scale_abs((val * brightness)/255, max);
-}
-
-/* Helper function to set one LED color and remember it for later */
-static void setrgb(int led, int red, int green, int blue)
-{
- int ctrl, bank;
- current[led][0] = red;
- current[led][1] = green;
- current[led][2] = blue;
- ctrl = led_to_ctrl[led];
- bank = led_to_isc[led];
- i2c_lock(I2C_PORT_LIGHTBAR, 1);
- controller_write(ctrl, bank, scale(blue, MAX_BLUE));
- controller_write(ctrl, bank+1, scale(red, MAX_RED));
- controller_write(ctrl, bank+2, scale(green, MAX_GREEN));
- i2c_lock(I2C_PORT_LIGHTBAR, 0);
-}
-
-/* LEDs are numbered 0-3, RGB values should be in 0-255.
- * If you specify too large an LED, it sets them all. */
-void lb_set_rgb(unsigned int led, int red, int green, int blue)
-{
- int i;
- if (led >= NUM_LEDS)
- for (i = 0; i < NUM_LEDS; i++)
- setrgb(i, red, green, blue);
- else
- setrgb(led, red, green, blue);
-}
-
-/* Get current LED values, if the LED number is in range. */
-int lb_get_rgb(unsigned int led, uint8_t *red, uint8_t *green, uint8_t *blue)
-{
- if (led < 0 || led >= NUM_LEDS)
- return EC_RES_INVALID_PARAM;
-
- *red = current[led][0];
- *green = current[led][1];
- *blue = current[led][2];
-
- return EC_RES_SUCCESS;
-}
-
-/* Change current display brightness (0-255) */
-void lb_set_brightness(unsigned int newval)
-{
- int i;
- CPRINTS("LB_bright 0x%02x", newval);
- brightness = newval;
- for (i = 0; i < NUM_LEDS; i++)
- setrgb(i, current[i][0], current[i][1], current[i][2]);
-}
-
-/* Get current display brightness (0-255) */
-uint8_t lb_get_brightness(void)
-{
- return brightness;
-}
-
-/* Initialize the controller ICs after reset */
-void lb_init(int use_lock)
-{
- int i;
-
- CPRINTF("[%pT LB_init_vals ", PRINTF_TIMESTAMP_NOW);
- for (i = 0; i < ARRAY_SIZE(init_vals); i++) {
- CPRINTF("%c", '0' + i % 10);
- if (use_lock)
- i2c_lock(I2C_PORT_LIGHTBAR, 1);
- controller_write(0, init_vals[i].reg, init_vals[i].val);
- controller_write(1, init_vals[i].reg, init_vals[i].val);
- if (use_lock)
- i2c_lock(I2C_PORT_LIGHTBAR, 0);
- }
- CPRINTF("]\n");
- memset(current, 0, sizeof(current));
-}
-
-/* Just go into standby mode. No register values should change. */
-void lb_off(void)
-{
- CPRINTS("LB_off");
- i2c_lock(I2C_PORT_LIGHTBAR, 1);
- controller_write(0, 0x01, 0x00);
- controller_write(1, 0x01, 0x00);
- i2c_lock(I2C_PORT_LIGHTBAR, 0);
-}
-
-/* Come out of standby mode. */
-void lb_on(void)
-{
- CPRINTS("LB_on");
- i2c_lock(I2C_PORT_LIGHTBAR, 1);
- controller_write(0, 0x01, 0x20);
- controller_write(1, 0x01, 0x20);
- i2c_lock(I2C_PORT_LIGHTBAR, 0);
-}
-
-static const uint8_t dump_reglist[] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a
-};
-
-/* Helper for host command to dump controller registers */
-void lb_hc_cmd_dump(struct ec_response_lightbar *out)
-{
- int i;
- uint8_t reg;
-
- BUILD_ASSERT(ARRAY_SIZE(dump_reglist) ==
- ARRAY_SIZE(out->dump.vals));
-
- for (i = 0; i < ARRAY_SIZE(dump_reglist); i++) {
- reg = dump_reglist[i];
- out->dump.vals[i].reg = reg;
- i2c_lock(I2C_PORT_LIGHTBAR, 1);
- out->dump.vals[i].ic0 = controller_read(0, reg);
- out->dump.vals[i].ic1 = controller_read(1, reg);
- i2c_lock(I2C_PORT_LIGHTBAR, 0);
- }
-}
-
-/* Helper for host command to write controller registers directly */
-void lb_hc_cmd_reg(const struct ec_params_lightbar *in)
-{
- i2c_lock(I2C_PORT_LIGHTBAR, 1);
- controller_write(in->reg.ctrl, in->reg.reg, in->reg.value);
- i2c_lock(I2C_PORT_LIGHTBAR, 0);
-}
diff --git a/common/led_common.c b/common/led_common.c
deleted file mode 100644
index 85879b148f..0000000000
--- a/common/led_common.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/* Copyright 2013 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.
- *
- * Common functions for blinking LEDs.
- */
-
-#include "console.h"
-#include "ec_commands.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "led_common.h"
-#include "util.h"
-
-#define LED_AUTO_CONTROL_FLAG(id) (1 << (id))
-
-static uint32_t led_auto_control_flags = ~0x00;
-
-static int led_is_supported(enum ec_led_id led_id)
-{
- int i;
- static int supported_leds = -1;
-
- if (supported_leds == -1) {
- supported_leds = 0;
-
- for (i = 0; i < supported_led_ids_count; i++)
- supported_leds |= (1 << supported_led_ids[i]);
- }
-
- return ((1 << (int)led_id) & supported_leds);
-}
-
-void led_auto_control(enum ec_led_id led_id, int enable)
-{
- if (enable)
- led_auto_control_flags |= LED_AUTO_CONTROL_FLAG(led_id);
- else
- led_auto_control_flags &= ~LED_AUTO_CONTROL_FLAG(led_id);
-}
-
-int led_auto_control_is_enabled(enum ec_led_id led_id)
-{
- if (!led_is_supported(led_id))
- return 0;
-
- return (led_auto_control_flags & LED_AUTO_CONTROL_FLAG(led_id)) != 0;
-}
-
-static enum ec_status led_command_control(struct host_cmd_handler_args *args)
-{
- const struct ec_params_led_control *p = args->params;
- struct ec_response_led_control *r = args->response;
- int i;
-
- args->response_size = sizeof(*r);
- memset(r->brightness_range, 0, sizeof(r->brightness_range));
-
- if (!led_is_supported(p->led_id))
- return EC_RES_INVALID_PARAM;
-
- led_get_brightness_range(p->led_id, r->brightness_range);
- if (p->flags & EC_LED_FLAGS_QUERY)
- return EC_RES_SUCCESS;
-
- for (i = 0; i < EC_LED_COLOR_COUNT; i++)
- if (r->brightness_range[i] == 0 && p->brightness[i] != 0)
- return EC_RES_INVALID_PARAM;
-
- if (p->flags & EC_LED_FLAGS_AUTO) {
- led_auto_control(p->led_id, 1);
- } else {
- if (led_set_brightness(p->led_id, p->brightness) != EC_SUCCESS)
- return EC_RES_INVALID_PARAM;
- led_auto_control(p->led_id, 0);
- }
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_LED_CONTROL, led_command_control, EC_VER_MASK(1));
-
-__attribute__((weak))
-void led_control(enum ec_led_id led_id, enum ec_led_state state)
-{
- /*
- * Default weak implementation that does not affect the state of
- * LED. Boards can provide their own implementation.
- */
-}
diff --git a/common/led_onoff_states.c b/common/led_onoff_states.c
deleted file mode 100644
index 48886e5de3..0000000000
--- a/common/led_onoff_states.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/* Copyright 2018 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.
- *
- * Power and battery LED state control
- */
-
-#include "battery.h"
-#include "charge_state.h"
-#include "chipset.h"
-#include "console.h"
-#include "ec_commands.h"
-#include "extpower.h"
-#include "hooks.h"
-#include "led_common.h"
-#include "led_onoff_states.h"
-#include "system.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_GPIO, format, ## args)
-
-/*
- * In order to support the battery LED being optional (ex. for Chromeboxes),
- * set up default battery table, setter, and variables.
- */
-__overridable struct led_descriptor
- led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES];
-__overridable const int led_charge_lvl_1;
-__overridable const int led_charge_lvl_2;
-__overridable void led_set_color_battery(enum ec_led_colors color)
-{
-}
-
-#ifndef CONFIG_CHARGER
-/* Include for the sake of compilation */
-int charge_get_percent(void);
-#endif
-
-static int led_get_charge_percent(void)
-{
- return DIV_ROUND_NEAREST(charge_get_display_charge(), 10);
-}
-
-static enum led_states led_get_state(void)
-{
- int charge_lvl;
- enum led_states new_state = LED_NUM_STATES;
-
- if (!IS_ENABLED(CONFIG_CHARGER))
- return new_state;
-
- switch (charge_get_state()) {
- case PWR_STATE_CHARGE:
- /* Get percent charge */
- charge_lvl = led_get_charge_percent();
- /* Determine which charge state to use */
- if (charge_lvl < led_charge_lvl_1)
- new_state = STATE_CHARGING_LVL_1;
- else if (charge_lvl < led_charge_lvl_2)
- new_state = STATE_CHARGING_LVL_2;
- else
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
- new_state = STATE_CHARGING_FULL_S5;
- else
- new_state = STATE_CHARGING_FULL_CHARGE;
- break;
- case PWR_STATE_DISCHARGE_FULL:
- if (extpower_is_present()) {
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
- new_state = STATE_CHARGING_FULL_S5;
- else
- new_state = STATE_CHARGING_FULL_CHARGE;
- break;
- }
- /* Intentional fall-through */
- case PWR_STATE_DISCHARGE /* and PWR_STATE_DISCHARGE_FULL */:
- if (chipset_in_state(CHIPSET_STATE_ON)) {
-#ifdef CONFIG_LED_ONOFF_STATES_BAT_LOW
- if (led_get_charge_percent() <
- CONFIG_LED_ONOFF_STATES_BAT_LOW)
- new_state = STATE_DISCHARGE_S0_BAT_LOW;
- else
-#endif
- new_state = STATE_DISCHARGE_S0;
- } else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND))
- new_state = STATE_DISCHARGE_S3;
- else
- new_state = STATE_DISCHARGE_S5;
- break;
- case PWR_STATE_ERROR:
- new_state = STATE_BATTERY_ERROR;
- break;
- case PWR_STATE_CHARGE_NEAR_FULL:
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
- new_state = STATE_CHARGING_FULL_S5;
- else
- new_state = STATE_CHARGING_FULL_CHARGE;
- break;
- case PWR_STATE_IDLE: /* External power connected in IDLE */
- if (charge_get_flags() & CHARGE_FLAG_FORCE_IDLE)
- new_state = STATE_FACTORY_TEST;
- else if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
- new_state = STATE_DISCHARGE_S5;
- else
- new_state = STATE_DISCHARGE_S0;
- break;
- default:
- /* Other states don't alter LED behavior */
- break;
- }
-
- return new_state;
-}
-
-__overridable enum led_states board_led_get_state(enum led_states desired_state)
-{
- return desired_state;
-}
-
-static void led_update_battery(void)
-{
- static uint8_t ticks, period;
- static int led_state = LED_NUM_STATES;
- int phase;
- enum led_states desired_state = led_get_state();
-
- desired_state = board_led_get_state(desired_state);
-
- /*
- * We always need to check the current state since the value could
- * have been manually overwritten. If we're in a new valid state,
- * update our ticks and period info. If our new state isn't defined,
- * continue using the previous one.
- */
- if (desired_state != led_state && desired_state < LED_NUM_STATES) {
- /*
- * Allow optional CHARGING_FULL_S5 state to fall back to
- * FULL_CHARGE if not defined.
- */
- if (desired_state == STATE_CHARGING_FULL_S5 &&
- led_bat_state_table[desired_state][LED_PHASE_0].time == 0)
- desired_state = STATE_CHARGING_FULL_CHARGE;
-
- /* State is changing */
- led_state = desired_state;
- /* Reset ticks and period when state changes */
- ticks = 0;
-
- period = led_bat_state_table[led_state][LED_PHASE_0].time +
- led_bat_state_table[led_state][LED_PHASE_1].time;
-
- }
-
- /* If this state is undefined, turn the LED off */
- if (period == 0) {
- CPRINTS("Undefined LED behavior for battery state %d,"
- "turning off LED", led_state);
- led_set_color_battery(LED_OFF);
- return;
- }
-
- /*
- * Determine which phase of the state table to use. The phase is
- * determined if it falls within first phase time duration.
- */
- phase = ticks < led_bat_state_table[led_state][LED_PHASE_0].time ?
- 0 : 1;
- ticks = (ticks + 1) % period;
-
- /* Set the color for the given state and phase */
- led_set_color_battery(led_bat_state_table[led_state][phase].color);
-}
-
-/*
- * In order to support the power LED being optional, set up default power LED
- * table and setter
- */
-__overridable const struct led_descriptor
- led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES];
-__overridable void led_set_color_power(enum ec_led_colors color)
-{
-}
-
-static enum pwr_led_states pwr_led_get_state(void)
-{
- if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) {
- if (extpower_is_present())
- return PWR_LED_STATE_SUSPEND_AC;
- else
- return PWR_LED_STATE_SUSPEND_NO_AC;
- } else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) {
- if (system_can_boot_ap())
- return PWR_LED_STATE_OFF;
- else
- return PWR_LED_STATE_OFF_LOW_POWER;
- } else if (chipset_in_state(CHIPSET_STATE_ON)) {
- return PWR_LED_STATE_ON;
- }
-
- return PWR_LED_NUM_STATES;
-}
-
-static void led_update_power(void)
-{
- static uint8_t ticks, period;
- static enum pwr_led_states led_state = PWR_LED_NUM_STATES;
- int phase;
- enum pwr_led_states desired_state = pwr_led_get_state();
-
- /*
- * If we're in a new valid state, update our ticks and period info.
- * Otherwise, continue to use old state
- */
- if (desired_state != led_state && desired_state < PWR_LED_NUM_STATES) {
- /*
- * Allow optional OFF_LOW_POWER state to fall back to
- * OFF not defined, as indicated by no specified phase 0 time.
- */
- if (desired_state == PWR_LED_STATE_OFF_LOW_POWER &&
- led_pwr_state_table[desired_state][LED_PHASE_0].time == 0)
- desired_state = PWR_LED_STATE_OFF;
-
- /* State is changing */
- led_state = desired_state;
- /* Reset ticks and period when state changes */
- ticks = 0;
-
- period = led_pwr_state_table[led_state][LED_PHASE_0].time +
- led_pwr_state_table[led_state][LED_PHASE_1].time;
-
- }
-
- /* If this state is undefined, turn the LED off */
- if (period == 0) {
- CPRINTS("Undefined LED behavior for power state %d,"
- "turning off LED", led_state);
- led_set_color_power(LED_OFF);
- return;
- }
-
- /*
- * Determine which phase of the state table to use. The phase is
- * determined if it falls within first phase time duration.
- */
- phase = ticks < led_pwr_state_table[led_state][LED_PHASE_0].time ?
- 0 : 1;
- ticks = (ticks + 1) % period;
-
- /* Set the color for the given state and phase */
- led_set_color_power(led_pwr_state_table[led_state][phase].color);
-
-}
-
-static void led_init(void)
-{
- /* If battery LED is enabled, set it to "off" to start with */
- if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED))
- led_set_color_battery(LED_OFF);
-
- /* If power LED is enabled, set it to "off" to start with */
- if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED))
- led_set_color_power(LED_OFF);
-
-}
-DECLARE_HOOK(HOOK_INIT, led_init, HOOK_PRIO_DEFAULT);
-
-/* Called by hook task every hook tick (200 msec) */
-static void led_update(void)
-{
- /*
- * If battery LED is enabled, set its state based on our power and
- * charge
- */
- if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED))
- led_update_battery();
- if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED))
- led_update_power();
-}
-DECLARE_HOOK(HOOK_TICK, led_update, HOOK_PRIO_DEFAULT);
diff --git a/common/led_policy_std.c b/common/led_policy_std.c
deleted file mode 100644
index e9fe4568a2..0000000000
--- a/common/led_policy_std.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/* Copyright 2015 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.
- *
- * Standard Battery LED and Power LED control
- * This assumes a red/green battery led and a single power led.
- */
-
-#include "gpio.h"
-#include "hooks.h"
-#include "battery.h"
-#include "charge_state.h"
-#include "chipset.h"
-#include "led_common.h"
-#include "util.h"
-#include "lid_switch.h"
-
-#ifdef CONFIG_LED_BAT_ACTIVE_LOW
-#define BAT_LED_ON 0
-#define BAT_LED_OFF 1
-#else
-#define BAT_LED_ON 1
-#define BAT_LED_OFF 0
-#endif
-
-#ifdef CONFIG_LED_POWER_ACTIVE_LOW
-#define POWER_LED_ON 0
-#define POWER_LED_OFF 1
-#else
-#define POWER_LED_ON 1
-#define POWER_LED_OFF 0
-#endif
-
-const enum ec_led_id supported_led_ids[] = {
- EC_LED_ID_BATTERY_LED, EC_LED_ID_POWER_LED};
-
-const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids);
-
-enum led_color {
- LED_OFF = 0,
- LED_RED,
- LED_AMBER,
- LED_GREEN,
- LED_WHITE,
- LED_COLOR_COUNT /* Number of colors, not a color itself */
-};
-
-static int bat_led_set_color(enum led_color color)
-{
- switch (color) {
- case LED_OFF:
- gpio_set_level(GPIO_BAT_LED_GREEN, BAT_LED_OFF);
- gpio_set_level(GPIO_BAT_LED_RED, BAT_LED_OFF);
- break;
- case LED_RED:
- gpio_set_level(GPIO_BAT_LED_GREEN, BAT_LED_OFF);
- gpio_set_level(GPIO_BAT_LED_RED, BAT_LED_ON);
- break;
- case LED_AMBER:
- gpio_set_level(GPIO_BAT_LED_GREEN, BAT_LED_ON);
- gpio_set_level(GPIO_BAT_LED_RED, BAT_LED_ON);
- break;
- case LED_GREEN:
- gpio_set_level(GPIO_BAT_LED_GREEN, BAT_LED_ON);
- gpio_set_level(GPIO_BAT_LED_RED, BAT_LED_OFF);
- break;
- default:
- return EC_ERROR_UNKNOWN;
- }
- return EC_SUCCESS;
-}
-
-static int pwr_led_set_color(enum led_color color)
-{
- switch (color) {
- case LED_OFF:
- gpio_set_level(GPIO_POWER_LED, POWER_LED_OFF);
- break;
- case LED_WHITE:
- gpio_set_level(GPIO_POWER_LED,
- lid_is_open() ? POWER_LED_ON : POWER_LED_OFF);
- break;
- default:
- return EC_ERROR_UNKNOWN;
- }
- return EC_SUCCESS;
-}
-
-void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range)
-{
- switch (led_id) {
- case EC_LED_ID_BATTERY_LED:
- brightness_range[EC_LED_COLOR_RED] = 1;
- brightness_range[EC_LED_COLOR_GREEN] = 1;
- break;
- case EC_LED_ID_POWER_LED:
- brightness_range[EC_LED_COLOR_WHITE] = 1;
- break;
- default:
- /* ignore */
- break;
- }
-}
-
-int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness)
-{
- switch (led_id) {
- case EC_LED_ID_BATTERY_LED:
- gpio_set_level(GPIO_BAT_LED_RED,
- (brightness[EC_LED_COLOR_RED] != 0) ?
- BAT_LED_ON : BAT_LED_OFF);
- gpio_set_level(GPIO_BAT_LED_GREEN,
- (brightness[EC_LED_COLOR_GREEN] != 0) ?
- BAT_LED_ON : BAT_LED_OFF);
- break;
- case EC_LED_ID_POWER_LED:
- gpio_set_level(GPIO_POWER_LED,
- (brightness[EC_LED_COLOR_WHITE] != 0) ?
- POWER_LED_ON : POWER_LED_OFF);
- break;
- default:
- return EC_ERROR_UNKNOWN;
- }
- return EC_SUCCESS;
-}
-
-#ifdef HAS_TASK_CHIPSET
-static void std_led_shutdown(void)
-{
- pwr_led_set_color(LED_OFF);
-}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, std_led_shutdown, HOOK_PRIO_DEFAULT);
-#endif
-
-static void std_led_set_power(void)
-{
- static int power_second;
-
- power_second++;
-
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
- pwr_led_set_color(LED_OFF);
- else if (chipset_in_state(CHIPSET_STATE_ON))
- pwr_led_set_color(LED_WHITE);
- else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND))
- pwr_led_set_color((power_second & 3) ? LED_OFF : LED_WHITE);
-}
-
-static void std_led_set_battery(void)
-{
- static int battery_second;
- uint32_t chflags = charge_get_flags();
-
- battery_second++;
-
- /* BAT LED behavior:
- * Same as the chromeos spec
- * Green/Amber for CHARGE_FLAG_FORCE_IDLE
- */
- switch (charge_get_state()) {
- case PWR_STATE_CHARGE:
- bat_led_set_color(LED_AMBER);
- break;
- case PWR_STATE_DISCHARGE:
- if (charge_get_percent() < 3)
- bat_led_set_color((battery_second & 1)
- ? LED_OFF : LED_AMBER);
- else if (charge_get_percent() < 10)
- bat_led_set_color((battery_second & 3)
- ? LED_OFF : LED_AMBER);
- else
- bat_led_set_color(LED_OFF);
- break;
- case PWR_STATE_ERROR:
- bat_led_set_color((battery_second & 1) ? LED_OFF : LED_RED);
- break;
- case PWR_STATE_CHARGE_NEAR_FULL:
- bat_led_set_color(LED_GREEN);
- break;
- case PWR_STATE_IDLE: /* External power connected in IDLE. */
- if (chflags & CHARGE_FLAG_FORCE_IDLE)
- bat_led_set_color(
- (battery_second & 0x2) ? LED_GREEN : LED_AMBER);
- else
- bat_led_set_color(LED_GREEN);
- break;
- default:
- /* Other states don't alter LED behavior */
- break;
- }
-}
-
-/** * Called by hook task every 1 sec */
-static void led_second(void)
-{
- if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED))
- std_led_set_power();
- if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED))
- std_led_set_battery();
-}
-DECLARE_HOOK(HOOK_SECOND, led_second, HOOK_PRIO_DEFAULT);
-
diff --git a/common/led_pwm.c b/common/led_pwm.c
deleted file mode 100644
index cc946ba522..0000000000
--- a/common/led_pwm.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/* Copyright 2018 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.
- */
-
-/* PWM LED control to conform to Chrome OS LED behaviour specification. */
-
-/*
- * This assumes that a single logical LED is shared between both power and
- * charging/battery status. If multiple logical LEDs are present, they all
- * follow the same patterns.
- */
-
-#include "battery.h"
-#include "charge_manager.h"
-#include "charge_state.h"
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "ec_commands.h"
-#include "hooks.h"
-#include "led_common.h"
-#include "led_pwm.h"
-#include "pwm.h"
-#include "timer.h"
-#include "util.h"
-
-/* Battery percentage thresholds to blink at different rates. */
-#define CRITICAL_LOW_BATTERY_PERCENTAGE 3
-#define LOW_BATTERY_PERCENTAGE 10
-
-#define PULSE_TICK (250 * MSEC)
-
-static uint8_t led_is_pulsing;
-
-static int get_led_id_color(enum pwm_led_id id, int color)
-{
-#ifdef CONFIG_LED_PWM_ACTIVE_CHARGE_PORT_ONLY
- int active_chg_port = charge_manager_get_active_charge_port();
-
- /* We should always be able to turn off a LED. */
- if (color == -1)
- return -1;
-
- if (led_is_pulsing)
- return color;
-
- /* The inactive charge port LEDs should be off. */
- if ((int)id != active_chg_port)
- return -1;
-#endif /* CONFIG_LED_PWM_ACTIVE_CHARGE_PORT_ONLY */
- return color;
-}
-
-void set_pwm_led_color(enum pwm_led_id id, int color)
-{
- struct pwm_led duty = { 0 };
- const struct pwm_led *led = &pwm_leds[id];
-
- if ((id >= CONFIG_LED_PWM_COUNT) || (id < 0) ||
- (color >= EC_LED_COLOR_COUNT) || (color < -1))
- return;
-
- if (color != -1) {
- duty.ch0 = led_color_map[color].ch0;
- duty.ch1 = led_color_map[color].ch1;
- duty.ch2 = led_color_map[color].ch2;
- }
-
- if (led->ch0 != (enum pwm_channel)PWM_LED_NO_CHANNEL)
- led->set_duty(led->ch0, duty.ch0);
- if (led->ch1 != (enum pwm_channel)PWM_LED_NO_CHANNEL)
- led->set_duty(led->ch1, duty.ch1);
- if (led->ch2 != (enum pwm_channel)PWM_LED_NO_CHANNEL)
- led->set_duty(led->ch2, duty.ch2);
-}
-
-static void set_led_color(int color)
-{
- /*
- * We must check if auto control is enabled since the LEDs may be
- * controlled from the AP at anytime.
- */
- if ((led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) ||
- (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)))
- set_pwm_led_color(PWM_LED0, get_led_id_color(PWM_LED0, color));
-
-#if CONFIG_LED_PWM_COUNT >= 2
- if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED))
- set_pwm_led_color(PWM_LED1, get_led_id_color(PWM_LED1, color));
-#endif /* CONFIG_LED_PWM_COUNT >= 2 */
-}
-
-static void set_pwm_led_enable(enum pwm_led_id id, int enable)
-{
- const struct pwm_led *led = &pwm_leds[id];
-
- if ((id >= CONFIG_LED_PWM_COUNT) || (id < 0))
- return;
-
- if (led->ch0 != (enum pwm_channel)PWM_LED_NO_CHANNEL)
- led->enable(led->ch0, enable);
- if (led->ch1 != (enum pwm_channel)PWM_LED_NO_CHANNEL)
- led->enable(led->ch1, enable);
- if (led->ch2 != (enum pwm_channel)PWM_LED_NO_CHANNEL)
- led->enable(led->ch2, enable);
-}
-
-static void init_leds_off(void)
-{
- /* Turn off LEDs such that they are in a known state with zero duty. */
- set_led_color(-1);
-
- /* Enable pwm modules for each channels of LEDs */
- set_pwm_led_enable(PWM_LED0, 1);
-
-#if CONFIG_LED_PWM_COUNT >= 2
- set_pwm_led_enable(PWM_LED1, 1);
-#endif /* CONFIG_LED_PWM_COUNT >= 2 */
-}
-DECLARE_HOOK(HOOK_INIT, init_leds_off, HOOK_PRIO_INIT_PWM + 1);
-
-static uint8_t pulse_period;
-static uint8_t pulse_ontime;
-static enum ec_led_colors pulse_color;
-static void update_leds(void);
-static void pulse_leds_deferred(void);
-DECLARE_DEFERRED(pulse_leds_deferred);
-static void pulse_leds_deferred(void)
-{
- static uint8_t tick_count;
-
- if (!led_is_pulsing) {
- tick_count = 0;
- /*
- * Since we're not pulsing anymore, turn the colors off in case
- * we were in the "on" time.
- */
- set_led_color(-1);
- /* Then show the desired state. */
- update_leds();
- return;
- }
-
- if (tick_count < pulse_ontime)
- set_led_color(pulse_color);
- else
- set_led_color(-1);
-
- tick_count = (tick_count + 1) % pulse_period;
- hook_call_deferred(&pulse_leds_deferred_data, PULSE_TICK);
-}
-
-static void pulse_leds(enum ec_led_colors color, int ontime, int period)
-{
- pulse_color = color;
- pulse_ontime = ontime;
- pulse_period = period;
- led_is_pulsing = 1;
- pulse_leds_deferred();
-}
-
-static int show_charge_state(void)
-{
- enum charge_state chg_st = charge_get_state();
-
- /*
- * The colors listed below are the default, but can be overridden.
- *
- * Solid Amber == Charging
- * Solid Green == Charging (near full)
- * Fast Flash Red == Charging error or battery not present
- */
- if (chg_st == PWR_STATE_CHARGE) {
- led_is_pulsing = 0;
- set_led_color(CONFIG_LED_PWM_CHARGE_COLOR);
- } else if (chg_st == PWR_STATE_CHARGE_NEAR_FULL ||
- chg_st == PWR_STATE_DISCHARGE_FULL) {
- led_is_pulsing = 0;
- set_led_color(CONFIG_LED_PWM_NEAR_FULL_COLOR);
- } else if ((battery_is_present() != BP_YES) ||
- (chg_st == PWR_STATE_ERROR)) {
- /* 500 ms period, 50% duty cycle. */
- pulse_leds(CONFIG_LED_PWM_CHARGE_ERROR_COLOR, 1, 2);
- } else {
- /* Discharging or not charging. */
-#ifdef CONFIG_LED_PWM_CHARGE_STATE_ONLY
- /*
- * If we only show the charge state, the only reason we
- * would pulse the LEDs is if we had an error. If it no longer
- * exists, stop pulsing the LEDs.
- */
- led_is_pulsing = 0;
-#endif /* CONFIG_LED_PWM_CHARGE_STATE_ONLY */
- return 0;
- }
- return 1;
-}
-
-#ifndef CONFIG_LED_PWM_CHARGE_STATE_ONLY
-static int show_battery_state(void)
-{
- int batt_percentage = charge_get_percent();
-
- /*
- * The colors listed below are the default, but can be overridden.
- *
- * Fast Flash Amber == Critical Battery
- * Slow Flash Amber == Low Battery
- */
- if (batt_percentage < CRITICAL_LOW_BATTERY_PERCENTAGE) {
- /* Flash amber faster (1 second period, 50% duty cycle) */
- pulse_leds(CONFIG_LED_PWM_LOW_BATT_COLOR, 2, 4);
- } else if (batt_percentage < LOW_BATTERY_PERCENTAGE) {
- /* Flash amber (4 second period, 50% duty cycle) */
- pulse_leds(CONFIG_LED_PWM_LOW_BATT_COLOR, 8, 16);
- } else {
- /* Sufficient charge, no need to show anything for this. */
- return 0;
- }
- return 1;
-}
-
-static int show_chipset_state(void)
-{
- /* Reflect the SoC state. */
- led_is_pulsing = 0;
- if (chipset_in_state(CHIPSET_STATE_ON)) {
- /* The LED must be on in the Active state. */
- set_led_color(CONFIG_LED_PWM_SOC_ON_COLOR);
- } else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) {
- /* The power LED must pulse in the suspend state. */
- pulse_leds(CONFIG_LED_PWM_SOC_SUSPEND_COLOR, 4, 16);
- } else {
- /* Chipset is off, no need to show anything for this. */
- return 0;
- }
- return 1;
-}
-#endif /* CONFIG_LED_PWM_CHARGE_STATE_ONLY */
-
-static void update_leds(void)
-{
- /* Reflecting the charge state is the highest priority. */
- if (show_charge_state())
- return;
-
-#ifndef CONFIG_LED_PWM_CHARGE_STATE_ONLY
- if (show_battery_state())
- return;
-
- if (show_chipset_state())
- return;
-#endif /* CONFIG_LED_PWM_CHARGE_STATE_ONLY */
-
- set_led_color(-1);
-}
-DECLARE_HOOK(HOOK_TICK, update_leds, HOOK_PRIO_DEFAULT);
-
-#ifdef CONFIG_CMD_LEDTEST
-int command_ledtest(int argc, char **argv)
-{
- int enable;
- int pwm_led_id;
- int led_id;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- pwm_led_id = atoi(argv[1]);
- if ((pwm_led_id < 0) || (pwm_led_id >= CONFIG_LED_PWM_COUNT))
- return EC_ERROR_PARAM1;
- led_id = supported_led_ids[pwm_led_id];
-
- if (argc == 2) {
- ccprintf("PWM LED %d: led_id=%d, auto_control=%d\n",
- pwm_led_id, led_id,
- led_auto_control_is_enabled(led_id) != 0);
- return EC_SUCCESS;
- }
- if (!parse_bool(argv[2], &enable))
- return EC_ERROR_PARAM2;
-
- /* Inverted because this drives auto control. */
- led_auto_control(led_id, !enable);
-
- if (argc == 4) {
- /* Set the color. */
- if (!strncmp(argv[3], "red", 3))
- set_pwm_led_color(pwm_led_id, EC_LED_COLOR_RED);
- else if (!strncmp(argv[3], "green", 5))
- set_pwm_led_color(pwm_led_id, EC_LED_COLOR_GREEN);
- else if (!strncmp(argv[3], "amber", 5))
- set_pwm_led_color(pwm_led_id, EC_LED_COLOR_AMBER);
- else if (!strncmp(argv[3], "blue", 4))
- set_pwm_led_color(pwm_led_id, EC_LED_COLOR_BLUE);
- else if (!strncmp(argv[3], "white", 5))
- set_pwm_led_color(pwm_led_id, EC_LED_COLOR_WHITE);
- else if (!strncmp(argv[3], "yellow", 6))
- set_pwm_led_color(pwm_led_id, EC_LED_COLOR_YELLOW);
- else if (!strncmp(argv[3], "off", 3))
- set_pwm_led_color(pwm_led_id, -1);
- else
- return EC_ERROR_PARAM3;
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(ledtest, command_ledtest,
- "<pwm led idx> <enable|disable> [color|off]", "");
-#endif /* defined(CONFIG_CMD_LEDTEST) */
diff --git a/common/lid_angle.c b/common/lid_angle.c
deleted file mode 100644
index 8a3775b959..0000000000
--- a/common/lid_angle.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/* Copyright 2014 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.
- */
-
-/* Lid angle module for Chrome EC */
-
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "hooks.h"
-#include "keyboard_scan.h"
-#include "lid_angle.h"
-#include "lid_switch.h"
-#include "math_util.h"
-#include "motion_lid.h"
-#include "motion_sense.h"
-#include "tablet_mode.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_LIDANGLE, outstr)
-#define CPRINTS(format, args...) cprints(CC_LIDANGLE, format, ## args)
-
-/*
- * Define the number of previous lid angle measurements to keep for determining
- * whether to enable or disable peripherals that are only needed for laptop
- * mode. These incude keyboard and trackpad. Note, that in order to change the
- * enable/disable state of these peripherals, all stored measurements of the
- * lid angle buffer must be in the specified range.
- */
-#define LID_ANGLE_BUFFER_SIZE 4
-
-/*
- * Define two variables to determine if wake source peripherals that are only
- * applicable for laptop mode should be enabled or disabled in S3 based on the
- * current lid angle. Note, the lid angle is bound to [0, 360]. Here are two
- * angles, defined such that we segregate the lid angle space into two regions.
- * The first region is the region in which we enable peripherals in S3 and is
- * when the lid angle CCW of the small_angle and CW of the large_angle. The
- * second region is the region in which we disable peripherals in S3 and is when
- * the lid angle is CCW of the large_angle and CW of the small_angle.
- *
- * Note, the most sensical values are small_angle = 0 and large_angle = 180,
- * but, the angle measurement is not perfect, and we know that if the angle is
- * near 0 and the lid isn't closed, then the lid must be near 360. So, the
- * small_angle is set to a small positive value to make sure we don't swap modes
- * when the lid is open all the way but is measuring a small positive value.
- */
-static int wake_large_angle = 180;
-static const int wake_small_angle = 13;
-
-/* Define hysteresis value to add stability to the flags. */
-#define LID_ANGLE_HYSTERESIS_DEG 2
-
-/* Define max and min values for wake_large_angle. */
-#define LID_ANGLE_MIN_LARGE_ANGLE 0
-#define LID_ANGLE_MAX_LARGE_ANGLE 360
-
-/**
- * Determine if given angle is in region to enable peripherals.
- *
- * @param ang Some lid angle in degrees [0, 360]
- *
- * @return true/false
- */
-static int lid_in_range_to_enable_peripherals(int ang)
-{
- /*
- * If the wake large angle is min or max, then this function should
- * return false or true respectively, independent of input angle.
- */
- if (wake_large_angle == LID_ANGLE_MIN_LARGE_ANGLE)
- return 0;
- else if (wake_large_angle == LID_ANGLE_MAX_LARGE_ANGLE)
- return 1;
-
- return (ang >= (wake_small_angle + LID_ANGLE_HYSTERESIS_DEG)) &&
- (ang <= (wake_large_angle - LID_ANGLE_HYSTERESIS_DEG));
-}
-
-/**
- * Determine if given angle is in region to ignore peripherals.
- *
- * @param ang Some lid angle in degrees [0, 360]
- *
- * @return true/false
- */
-static int lid_in_range_to_ignore_peripherals(int ang)
-{
- /*
- * If the wake large angle is min or max, then this function should
- * return true or false respectively, independent of input angle.
- */
- if (wake_large_angle == LID_ANGLE_MIN_LARGE_ANGLE)
- return 1;
- else if (wake_large_angle == LID_ANGLE_MAX_LARGE_ANGLE)
- return 0;
-
- return (ang <= (wake_small_angle - LID_ANGLE_HYSTERESIS_DEG)) ||
- (ang >= (wake_large_angle + LID_ANGLE_HYSTERESIS_DEG));
-}
-
-
-int lid_angle_get_wake_angle(void)
-{
- return wake_large_angle;
-}
-
-void lid_angle_set_wake_angle(int ang)
-{
- if (ang < LID_ANGLE_MIN_LARGE_ANGLE)
- ang = LID_ANGLE_MIN_LARGE_ANGLE;
- else if (ang > LID_ANGLE_MAX_LARGE_ANGLE)
- ang = LID_ANGLE_MAX_LARGE_ANGLE;
-
- wake_large_angle = ang;
-}
-
-void lid_angle_update(int lid_ang)
-{
- static int lidangle_buffer[LID_ANGLE_BUFFER_SIZE];
- static int index;
- int i;
- int accept = 1, ignore = 1;
-
- /* Record most recent lid angle in circular buffer. */
- lidangle_buffer[index] = lid_ang;
- index = (index == LID_ANGLE_BUFFER_SIZE-1) ? 0 : index+1;
-
- /*
- * Manage whether or not peripherals are enabled based on lid angle
- * history.
- */
- for (i = 0; i < LID_ANGLE_BUFFER_SIZE; i++) {
- /*
- * If any lid angle samples are unreliable, then
- * don't change peripheral state.
- */
- if (lidangle_buffer[i] == LID_ANGLE_UNRELIABLE)
- return;
-
- /*
- * Force all elements of the lid angle buffer to be
- * in range of one of the conditions in order to change
- * to the corresponding peripheral state.
- */
- if (!lid_in_range_to_enable_peripherals(lidangle_buffer[i]))
- accept = 0;
- if (!lid_in_range_to_ignore_peripherals(lidangle_buffer[i]))
- ignore = 0;
- }
-
- /* Enable or disable peripherals as necessary. */
- if (accept)
- lid_angle_peripheral_enable(1);
- else if (ignore && !accept)
- lid_angle_peripheral_enable(0);
-}
-
-static void enable_peripherals(void)
-{
- /*
- * Make sure lid angle is not disabling peripherals when AP is running.
- */
- lid_angle_peripheral_enable(1);
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, enable_peripherals, HOOK_PRIO_DEFAULT);
-
-#ifdef CONFIG_TABLET_MODE
-static void suspend_peripherals(void)
-{
- /*
- * Make sure peripherals are disabled in S3 in tablet mode.
- */
- if (tablet_get_mode())
- lid_angle_peripheral_enable(0);
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, suspend_peripherals, HOOK_PRIO_DEFAULT);
-#endif /* CONFIG_TABLET_MODE */
-
-#ifdef TEST_BUILD
-__overridable void lid_angle_peripheral_enable(int enable)
-{
-}
-#else
-__overridable void lid_angle_peripheral_enable(int enable)
-{
- int chipset_in_s0 = chipset_in_state(CHIPSET_STATE_ON);
-
- if (enable) {
- keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE);
- } else {
- /*
- * Ensure that the chipset is off before disabling the keyboard.
- * When the chipset is on, the EC keeps the keyboard enabled and
- * the AP decides whether to ignore input devices or not.
- */
- if (!chipset_in_s0)
- keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE);
- }
-}
-#endif /* TEST_BUILD */
diff --git a/common/lightbar.c b/common/lightbar.c
deleted file mode 100644
index f80287941d..0000000000
--- a/common/lightbar.c
+++ /dev/null
@@ -1,2068 +0,0 @@
-/*
- * Copyright 2012 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.
- *
- * LED controls.
- */
-
-#ifdef LIGHTBAR_SIMULATION
-#include "simulation.h"
-#else
-#include "battery.h"
-#include "charge_state.h"
-#include "common.h"
-#include "console.h"
-#include "ec_commands.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "lb_common.h"
-#include "lightbar.h"
-#include "lid_switch.h"
-#include "motion_sense.h"
-#include "pwm.h"
-#include "system.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-#endif
-
-/*
- * The Link lightbar had no version command, so defaulted to zero. We have
- * added a couple of new commands, so we've updated the version. Any
- * optional features in the current version should be marked with flags.
- */
-#define LIGHTBAR_IMPLEMENTATION_VERSION 1
-#define LIGHTBAR_IMPLEMENTATION_FLAGS 0
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_LIGHTBAR, outstr)
-#define CPRINTS(format, args...) cprints(CC_LIGHTBAR, format, ## args)
-
-#define FP_SCALE 10000
-
-/******************************************************************************/
-/* Here's some state that we might want to maintain across sysjumps, just to
- * prevent the lightbar from flashing during normal boot as the EC jumps from
- * RO to RW. */
-static struct p_state {
- /* What patterns are we showing? */
- enum lightbar_sequence cur_seq;
- enum lightbar_sequence prev_seq;
-
- /* Quantized battery charge level: 0=low 1=med 2=high 3=full. */
- int battery_level;
- int battery_percent;
-
- /* It's either charging or discharging. */
- int battery_is_charging;
-
- /* Is power-on prevented due to battery level? */
- int battery_is_power_on_prevented;
-
- /* Pattern variables for state S0. */
- uint16_t w0; /* primary phase */
- uint8_t ramp; /* ramp-in for S3->S0 */
-
- uint8_t _pad0; /* next item is __packed */
-
- /* Tweakable parameters. */
- union {
- struct lightbar_params_v1 p;
- struct {
- struct lightbar_params_v2_timing timing;
- struct lightbar_params_v2_tap tap;
- struct lightbar_params_v2_oscillation osc;
- struct lightbar_params_v2_brightness bright;
- struct lightbar_params_v2_thresholds thlds;
- struct lightbar_params_v2_colors colors;
- } p_v2;
- };
-} st;
-
-/* Each of the parameters must be less than 120 bytes
- * (crbug.com/467716)
- */
-#define MAX_PARAM_SIZE 120
-BUILD_ASSERT(sizeof(struct lightbar_params_v2_timing) <= MAX_PARAM_SIZE);
-BUILD_ASSERT(sizeof(struct lightbar_params_v2_tap) <= MAX_PARAM_SIZE);
-BUILD_ASSERT(sizeof(struct lightbar_params_v2_oscillation) <= MAX_PARAM_SIZE);
-BUILD_ASSERT(sizeof(struct lightbar_params_v2_brightness) <= MAX_PARAM_SIZE);
-BUILD_ASSERT(sizeof(struct lightbar_params_v2_thresholds) <= MAX_PARAM_SIZE);
-BUILD_ASSERT(sizeof(struct lightbar_params_v2_colors) <= MAX_PARAM_SIZE);
-#undef MAX_PARAM_SIZE
-
-#define PRIMARY_BLUE 4
-#define PRIMARY_RED 5
-#define PRIMARY_YELLOW 6
-#define PRIMARY_GREEN 7
-
-static const struct lightbar_params_v1 default_params = {
- .google_ramp_up = 2500,
- .google_ramp_down = 10000,
- .s3s0_ramp_up = 2000,
- .s0_tick_delay = { 45000, 30000 }, /* battery, AC */
- .s0a_tick_delay = { 5000, 3000 }, /* battery, AC */
- .s0s3_ramp_down = 2000,
- .s3_sleep_for = 5 * SECOND, /* between checks */
- .s3_ramp_up = 2500,
- .s3_ramp_down = 10000,
- .s5_ramp_up = 2500,
- .s5_ramp_down = 10000,
- .tap_tick_delay = 5000, /* oscillation step time */
- .tap_gate_delay = 200 * MSEC, /* segment gating delay */
- .tap_display_time = 3 * SECOND, /* total sequence time */
-
- /* TODO (crosbug.com/p/36996): remove unused tap_pct_red */
- .tap_pct_red = 14, /* below this is red */
- .tap_pct_green = 94, /* above this is green */
- .tap_seg_min_on = 35, /* min intensity (%) for "on" */
- .tap_seg_max_on = 100, /* max intensity (%) for "on" */
- .tap_seg_osc = 50, /* amplitude for charging osc */
- .tap_idx = {PRIMARY_RED, PRIMARY_YELLOW, PRIMARY_GREEN}, /* color */
-
- .osc_min = { 0x60, 0x60 }, /* battery, AC */
- .osc_max = { 0xd0, 0xd0 }, /* battery, AC */
- .w_ofs = {24, 24}, /* phase offset, 256 == 2*PI */
-
- .bright_bl_off_fixed = {0xcc, 0xff}, /* backlight off: battery, AC */
- .bright_bl_on_min = {0xcc, 0xff}, /* backlight on: battery, AC */
- .bright_bl_on_max = {0xcc, 0xff}, /* backlight on: battery, AC */
-
- .battery_threshold = { 14, 40, 99 }, /* percent, lowest to highest */
- .s0_idx = {
- /* battery: 0 = red, other = blue */
- { PRIMARY_RED, PRIMARY_BLUE, PRIMARY_BLUE, PRIMARY_BLUE },
- /* AC: always blue */
- { PRIMARY_BLUE, PRIMARY_BLUE, PRIMARY_BLUE, PRIMARY_BLUE }
- },
- .s3_idx = {
- /* battery: 0 = red, else off */
- { PRIMARY_RED, 0xff, 0xff, 0xff },
- /* AC: do nothing */
- { 0xff, 0xff, 0xff, 0xff }
- },
- .s5_idx = PRIMARY_RED, /* flash red */
- .color = {
- /*
- * These values have been optically calibrated for the
- * Samus LEDs to best match the official colors, described at
- * https://sites.google.com/a/google.com/brandsite/the-colours
- * See crosbug.com/p/33017 before making any changes.
- */
- {0x34, 0x70, 0xb4}, /* 0: Google blue */
- {0xbc, 0x50, 0x2c}, /* 1: Google red */
- {0xd0, 0xe0, 0x00}, /* 2: Google yellow */
- {0x50, 0xa0, 0x40}, /* 3: Google green */
- /* These are primary colors */
- {0x00, 0x00, 0xff}, /* 4: full blue */
- {0xff, 0x00, 0x00}, /* 5: full red */
- {0xff, 0xff, 0x00}, /* 6: full yellow */
- {0x00, 0xff, 0x00}, /* 7: full green */
- },
-};
-
-#define LB_SYSJUMP_TAG 0x4c42 /* "LB" */
-static void lightbar_preserve_state(void)
-{
- system_add_jump_tag(LB_SYSJUMP_TAG, 0, sizeof(st), &st);
-}
-DECLARE_HOOK(HOOK_SYSJUMP, lightbar_preserve_state, HOOK_PRIO_DEFAULT);
-
-static void lightbar_restore_state(void)
-{
- const uint8_t *old_state = 0;
- int size;
-
- old_state = system_get_jump_tag(LB_SYSJUMP_TAG, 0, &size);
- if (old_state && size == sizeof(st)) {
- memcpy(&st, old_state, size);
- CPRINTS("LB state restored: %d %d - %d %d/%d",
- st.cur_seq, st.prev_seq,
- st.battery_is_charging,
- st.battery_percent,
- st.battery_level);
- } else {
- st.cur_seq = st.prev_seq = LIGHTBAR_S5;
- st.battery_percent = 100;
- st.battery_level = LB_BATTERY_LEVELS - 1;
- st.w0 = 0;
- st.ramp = 0;
- memcpy(&st.p, &default_params, sizeof(st.p));
- CPRINTS("LB state initialized");
- }
-}
-
-/******************************************************************************/
-/* The patterns are generally dependent on the current battery level and AC
- * state. These functions obtain that information, generally by querying the
- * power manager task. In demo mode, the keyboard task forces changes to the
- * state by calling the demo_* functions directly. */
-/******************************************************************************/
-
-#ifdef CONFIG_PWM_KBLIGHT
-static int last_backlight_level;
-#endif
-#ifdef CONFIG_ALS_LIGHTBAR_DIMMING
-test_export_static int google_color_id;
-#endif
-
-static int demo_mode = DEMO_MODE_DEFAULT;
-
-static int quantize_battery_level(int pct)
-{
- int i, bl = 0;
- for (i = 0; i < LB_BATTERY_LEVELS - 1; i++)
- if (pct >= st.p.battery_threshold[i])
- bl++;
- return bl;
-}
-
-#ifdef CONFIG_ALS_LIGHTBAR_DIMMING
-test_export_static int lux_level_to_google_color(const int lux)
-{
- int i;
-
- if (!lid_is_open()) {
- /* The lid shades the light sensor, use full brightness. */
- if (google_color_id != 0) {
- google_color_id = 0;
- return 1;
- } else {
- return 0;
- }
- }
-
- /* See if we need to decrease brightness */
- for (i = google_color_id; i < lb_brightness_levels_count ; i++)
- if (lux >= lb_brightness_levels[i].lux_down)
- break;
- if (i > google_color_id) {
- google_color_id = i;
- return 1;
- }
- /* See if we need to increase brightness */
- for (i = google_color_id; i > 0; i--)
- if (lux < lb_brightness_levels[i - 1].lux_up)
- break;
- if (i < google_color_id) {
- google_color_id = i;
- return 1;
- }
- return 0;
-}
-#endif
-
-/*
- * Update the known state.
- * Return 1 if something changes.
- */
-static int get_battery_level(void)
-{
- int pct = 0;
- int bl, change = 0;
-
- if (demo_mode)
- return 0;
-
-#ifdef HAS_TASK_CHARGER
- st.battery_percent = pct = charge_get_percent();
- st.battery_is_charging = (PWR_STATE_DISCHARGE != charge_get_state());
- st.battery_is_power_on_prevented = charge_prevent_power_on(0);
-#endif
-
- /* Find the new battery level */
- bl = quantize_battery_level(pct);
-
- /* Use some hysteresis to avoid flickering */
- if (bl < st.battery_level ||
- (bl > st.battery_level
- && pct >= (st.p.battery_threshold[st.battery_level] + 1))) {
- st.battery_level = bl;
- change = 1;
- }
-
-#ifdef CONFIG_PWM_KBLIGHT
- /*
- * With nothing else to go on, use the keyboard backlight level to *
- * set the brightness. In general, if the keyboard backlight
- * is OFF (which it is when ambient is bright), use max brightness for
- * lightbar. If keyboard backlight is ON, use keyboard backlight
- * brightness. That fails if the keyboard backlight is off because
- * someone's watching a movie in the dark, of course. Ideally we should
- * just let the AP control it directly.
- */
- if (pwm_get_enabled(PWM_CH_KBLIGHT)) {
- pct = pwm_get_duty(PWM_CH_KBLIGHT);
- pct = (255 * pct) / 100; /* 00 - FF */
- if (pct > st.p.bright_bl_on_max[st.battery_is_charging])
- pct = st.p.bright_bl_on_max[st.battery_is_charging];
- else if (pct < st.p.bright_bl_on_min[st.battery_is_charging])
- pct = st.p.bright_bl_on_min[st.battery_is_charging];
- } else
- pct = st.p.bright_bl_off_fixed[st.battery_is_charging];
-
- if (pct != last_backlight_level) {
- last_backlight_level = pct;
- lb_set_brightness(pct);
- change = 1;
- }
-#endif
-#ifdef CONFIG_ALS_LIGHTBAR_DIMMING
- /* Read last value (in lux) collected by the motion sensor. */
- /* Convert lux into brightness percentage */
- if (lux_level_to_google_color(MOTION_SENSE_LUX)) {
- memcpy(st.p.color, lb_brightness_levels[google_color_id].color,
- sizeof(lb_brightness_levels[google_color_id].color));
- change = 1;
- }
-#endif
- return change;
-}
-
-/* Forcing functions for demo mode, called by the keyboard task. */
-
-/* Up/Down keys */
-#define DEMO_CHARGE_STEP 1
-void demo_battery_level(int inc)
-{
- if (!demo_mode)
- return;
-
- st.battery_percent += DEMO_CHARGE_STEP * inc;
-
- if (st.battery_percent > 100)
- st.battery_percent = 100;
- else if (st.battery_percent < 0)
- st.battery_percent = 0;
-
- st.battery_level = quantize_battery_level(st.battery_percent);
-
- CPRINTS("LB demo: battery_percent = %d%%, battery_level=%d",
- st.battery_percent, st.battery_level);
-}
-
-/* Left/Right keys */
-
-void demo_is_charging(int ischarge)
-{
- if (!demo_mode)
- return;
-
- st.battery_is_charging = ischarge;
- CPRINTS("LB demo: battery_is_charging=%d",
- st.battery_is_charging);
-}
-
-/* Bright/Dim keys */
-void demo_brightness(int inc)
-{
- int b;
-
- if (!demo_mode)
- return;
-
- b = lb_get_brightness() + (inc * 16);
- if (b > 0xff)
- b = 0xff;
- else if (b < 0)
- b = 0;
- lb_set_brightness(b);
-}
-
-/* T key */
-void demo_tap(void)
-{
- if (!demo_mode)
- return;
- lightbar_sequence(LIGHTBAR_TAP);
-}
-
-/******************************************************************************/
-/* Helper functions and data. */
-/******************************************************************************/
-
-#define F(x) (x * FP_SCALE)
-static const uint16_t _ramp_table[] = {
- F(0.000000), F(0.002408), F(0.009607), F(0.021530), F(0.038060),
- F(0.059039), F(0.084265), F(0.113495), F(0.146447), F(0.182803),
- F(0.222215), F(0.264302), F(0.308658), F(0.354858), F(0.402455),
- F(0.450991), F(0.500000), F(0.549009), F(0.597545), F(0.645142),
- F(0.691342), F(0.735698), F(0.777785), F(0.817197), F(0.853553),
- F(0.886505), F(0.915735), F(0.940961), F(0.961940), F(0.978470),
- F(0.990393), F(0.997592), F(1.000000),
-};
-#undef F
-
-/* This function provides a smooth ramp up from 0.0 to 1.0 and back to 0.0,
- * for input from 0x00 to 0xff. */
-static inline int cycle_010(uint8_t i)
-{
- uint8_t bucket, index;
-
- if (i == 128)
- return FP_SCALE;
- else if (i > 128)
- i = 256 - i;
-
- bucket = i >> 2;
- index = i & 0x3;
-
- return _ramp_table[bucket] +
- ((_ramp_table[bucket + 1] - _ramp_table[bucket]) * index >> 2);
-}
-
-/******************************************************************************/
-/* Here's where we keep messages waiting to be delivered to the lightbar task.
- * If more than one is sent before the task responds, we only want to deliver
- * the latest one. */
-static uint32_t pending_msg;
-/* And here's the task event that we use to trigger delivery. */
-#define PENDING_MSG TASK_EVENT_CUSTOM_BIT(0)
-
-/* Interruptible delay. */
-#define WAIT_OR_RET(A) \
- do { \
- uint32_t msg = task_wait_event(A); \
- uint32_t p_msg = pending_msg; \
- if (msg & PENDING_MSG && p_msg != st.cur_seq) \
- return p_msg; \
- } while (0)
-
-/******************************************************************************/
-/* Here are the preprogrammed sequences. */
-/******************************************************************************/
-
-/* Pulse google colors once, off to on to off. */
-static uint32_t pulse_google_colors(void)
-{
- int w, i, r, g, b;
- int f;
-
- for (w = 0; w < 128; w += 2) {
- f = cycle_010(w);
- for (i = 0; i < NUM_LEDS; i++) {
- r = st.p.color[i].r * f / FP_SCALE;
- g = st.p.color[i].g * f / FP_SCALE;
- b = st.p.color[i].b * f / FP_SCALE;
- lb_set_rgb(i, r, g, b);
- }
- WAIT_OR_RET(st.p.google_ramp_up);
- }
- for (w = 128; w <= 256; w++) {
- f = cycle_010(w);
- for (i = 0; i < NUM_LEDS; i++) {
- r = st.p.color[i].r * f / FP_SCALE;
- g = st.p.color[i].g * f / FP_SCALE;
- b = st.p.color[i].b * f / FP_SCALE;
- lb_set_rgb(i, r, g, b);
- }
- WAIT_OR_RET(st.p.google_ramp_down);
- }
-
- return 0;
-}
-
-/* CPU is waking from sleep. */
-static uint32_t sequence_S3S0(void)
-{
- int w, r, g, b;
- int f, fmin;
- int ci;
- uint32_t res;
-
- lb_init(1);
- lb_on();
- get_battery_level();
-
- res = pulse_google_colors();
- if (res)
- return res;
-
-#ifndef BLUE_PULSING
- /* next sequence */
- return LIGHTBAR_S0;
-#endif
-
- /* Ramp up to starting brightness, using S0 colors */
- ci = st.p.s0_idx[st.battery_is_charging][st.battery_level];
- if (ci >= ARRAY_SIZE(st.p.color))
- ci = 0;
-
- fmin = st.p.osc_min[st.battery_is_charging] * FP_SCALE / 255;
-
- for (w = 0; w <= 128; w++) {
- f = cycle_010(w) * fmin / FP_SCALE;
- r = st.p.color[ci].r * f / FP_SCALE;
- g = st.p.color[ci].g * f / FP_SCALE;
- b = st.p.color[ci].b * f / FP_SCALE;
- lb_set_rgb(NUM_LEDS, r, g, b);
- WAIT_OR_RET(st.p.s3s0_ramp_up);
- }
-
- /* Initial conditions */
- st.w0 = -256; /* start cycle_npn() quietly */
- st.ramp = 0;
-
- /* Ready for S0 */
- return LIGHTBAR_S0;
-}
-
-#ifdef BLUE_PULSING
-
-/* This function provides a pulsing oscillation between -0.5 and +0.5. */
-static inline int cycle_npn(uint16_t i)
-{
- if ((i / 256) % 4)
- return -FP_SCALE / 2;
- return cycle_010(i) - FP_SCALE / 2;
-}
-
-/* CPU is fully on */
-static uint32_t sequence_S0(void)
-{
- int tick, last_tick;
- timestamp_t start, now;
- uint8_t r, g, b;
- int i, ci;
- uint8_t w_ofs;
- uint16_t w;
- int f, fmin, fmax, base_s0, osc_s0, f_ramp;
-
- start = get_time();
- tick = last_tick = 0;
-
- lb_set_rgb(NUM_LEDS, 0, 0, 0);
- lb_on();
-
- while (1) {
- now = get_time();
-
- /* Only check the battery state every few seconds. The battery
- * charging task doesn't update as quickly as we do, and isn't
- * always valid for a bit after jumping from RO->RW. */
- tick = (now.le.lo - start.le.lo) / SECOND;
- if (tick % 4 == 3 && tick != last_tick) {
- get_battery_level();
- last_tick = tick;
- }
-
- /* Calculate the colors */
- ci = st.p.s0_idx[st.battery_is_charging][st.battery_level];
- if (ci >= ARRAY_SIZE(st.p.color))
- ci = 0;
- w_ofs = st.p.w_ofs[st.battery_is_charging];
- fmin = st.p.osc_min[st.battery_is_charging] * FP_SCALE / 255;
- fmax = st.p.osc_max[st.battery_is_charging] * FP_SCALE / 255;
- base_s0 = (fmax + fmin) / 2;
- osc_s0 = fmax - fmin;
- f_ramp = st.ramp * FP_SCALE / 255;
-
- for (i = 0; i < NUM_LEDS; i++) {
- w = st.w0 - i * w_ofs * f_ramp / FP_SCALE;
- f = base_s0 + osc_s0 * cycle_npn(w) / FP_SCALE;
- r = st.p.color[ci].r * f / FP_SCALE;
- g = st.p.color[ci].g * f / FP_SCALE;
- b = st.p.color[ci].b * f / FP_SCALE;
- lb_set_rgb(i, r, g, b);
- }
-
- /* Increment the phase */
- if (st.battery_is_charging)
- st.w0--;
- else
- st.w0++;
-
- /* Continue ramping in if needed */
- if (st.ramp < 0xff)
- st.ramp++;
-
- i = st.p.s0a_tick_delay[st.battery_is_charging];
- WAIT_OR_RET(i);
- }
- return 0;
-}
-
-#else /* just simple google colors */
-
-static uint32_t sequence_S0(void)
-{
- int w, i, r, g, b;
- int f, change;
-
- lb_set_rgb(NUM_LEDS, 0, 0, 0);
- lb_on();
-
- /* Ramp up */
- for (w = 0; w < 128; w += 2) {
- f = cycle_010(w);
- for (i = 0; i < NUM_LEDS; i++) {
- r = st.p.color[i].r * f / FP_SCALE;
- g = st.p.color[i].g * f / FP_SCALE;
- b = st.p.color[i].b * f / FP_SCALE;
- lb_set_rgb(i, r, g, b);
- }
- WAIT_OR_RET(st.p.google_ramp_up);
- }
-
- while (1) {
- change = get_battery_level();
-
- if (change) {
- /* Not really low use google colors */
- if (st.battery_level) {
- for (i = 0; i < NUM_LEDS; i++) {
- r = st.p.color[i].r;
- g = st.p.color[i].g;
- b = st.p.color[i].b;
- lb_set_rgb(i, r, g, b);
- }
- } else {
- r = st.p.color[PRIMARY_RED].r;
- g = st.p.color[PRIMARY_RED].g;
- b = st.p.color[PRIMARY_RED].b;
- lb_set_rgb(4, r, g, b);
- }
- }
-
- WAIT_OR_RET(1 * SECOND);
- }
- return 0;
-}
-
-#endif
-
-/* CPU is going to sleep. */
-static uint32_t sequence_S0S3(void)
-{
- int w, i, r, g, b;
- int f;
- uint8_t drop[NUM_LEDS][3];
- uint32_t res;
-
- /* Grab current colors */
- for (i = 0; i < NUM_LEDS; i++)
- lb_get_rgb(i, &drop[i][0], &drop[i][1], &drop[i][2]);
-
- /* Fade down to black */
- for (w = 128; w <= 256; w++) {
- f = cycle_010(w);
- for (i = 0; i < NUM_LEDS; i++) {
- r = drop[i][0] * f / FP_SCALE;
- g = drop[i][1] * f / FP_SCALE;
- b = drop[i][2] * f / FP_SCALE;
- lb_set_rgb(i, r, g, b);
- }
- WAIT_OR_RET(st.p.s0s3_ramp_down);
- }
-
- /* pulse once and done */
- res = pulse_google_colors();
- if (res)
- return res;
-
- /* next sequence */
- return LIGHTBAR_S3;
-}
-
-/* CPU is sleeping */
-static uint32_t sequence_S3(void)
-{
- int r, g, b;
- int w;
- int f;
- int ci;
-
- lb_off();
- lb_init(1);
- lb_set_rgb(NUM_LEDS, 0, 0, 0);
- get_battery_level();
- while (1) {
- WAIT_OR_RET(st.p.s3_sleep_for);
-
- /* only pulse if we've been given a valid color index */
- ci = st.p.s3_idx[st.battery_is_charging][st.battery_level];
- if (ci >= ARRAY_SIZE(st.p.color))
- continue;
-
- /* pulse once */
- lb_on();
-
- for (w = 0; w < 128; w += 2) {
- f = cycle_010(w);
- r = st.p.color[ci].r * f / FP_SCALE;
- g = st.p.color[ci].g * f / FP_SCALE;
- b = st.p.color[ci].b * f / FP_SCALE;
- lb_set_rgb(NUM_LEDS, r, g, b);
- WAIT_OR_RET(st.p.s3_ramp_up);
- }
- for (w = 128; w <= 256; w++) {
- f = cycle_010(w);
- r = st.p.color[ci].r * f / FP_SCALE;
- g = st.p.color[ci].g * f / FP_SCALE;
- b = st.p.color[ci].b * f / FP_SCALE;
- lb_set_rgb(NUM_LEDS, r, g, b);
- WAIT_OR_RET(st.p.s3_ramp_down);
- }
-
- lb_set_rgb(NUM_LEDS, 0, 0, 0);
- lb_off();
- }
- return 0;
-}
-
-
-/* CPU is powering up. We generally boot fast enough that we don't have time
- * to do anything interesting in the S3 state, but go straight on to S0. */
-static uint32_t sequence_S5S3(void)
-{
- /* The controllers need 100us after power is applied before they'll
- * respond. Don't return early, because we still want to initialize the
- * lightbar even if another message comes along while we're waiting. */
- usleep(100);
- lb_init(1);
- lb_set_rgb(NUM_LEDS, 0, 0, 0);
- lb_on();
- /* next sequence */
- return LIGHTBAR_S3;
-}
-
-/* Sleep to off. The S3->S5 transition takes about 10msec, so just wait. */
-static uint32_t sequence_S3S5(void)
-{
- lb_off();
- /* next sequence */
- return LIGHTBAR_S5;
-}
-
-/* Pulse S5 color to indicate that the battery is so critically low that it
- * must charge first before the system can power on. */
-static uint32_t pulse_s5_color(void)
-{
- int r, g, b;
- int f;
- int w;
- struct rgb_s *color = &st.p.color[st.p.s5_idx];
-
- for (w = 0; w < 128; w += 2) {
- f = cycle_010(w);
- r = color->r * f / FP_SCALE;
- g = color->g * f / FP_SCALE;
- b = color->b * f / FP_SCALE;
- lb_set_rgb(NUM_LEDS, r, g, b);
- WAIT_OR_RET(st.p.s5_ramp_up);
- }
- for (w = 128; w <= 256; w++) {
- f = cycle_010(w);
- r = color->r * f / FP_SCALE;
- g = color->g * f / FP_SCALE;
- b = color->b * f / FP_SCALE;
- lb_set_rgb(NUM_LEDS, r, g, b);
- WAIT_OR_RET(st.p.s5_ramp_down);
- }
-
- return 0;
-}
-
-/* CPU is off. Pulse the lightbar if a charger is attached and the battery is
- * so low that the system cannot power on. Otherwise, the lightbar loses power
- * when the CPU is in S5, so there's nothing to do. We'll just wait here until
- * the state changes. */
-static uint32_t sequence_S5(void)
-{
- int initialized = 0;
- uint32_t res = 0;
-
- get_battery_level();
- while (1) {
- if (!st.battery_is_power_on_prevented ||
- !st.battery_is_charging)
- break;
-
- if (!initialized) {
-#ifdef CONFIG_LIGHTBAR_POWER_RAILS
- /* Request that lightbar power rails be turned on. */
- if (lb_power(1)) {
- lb_set_rgb(NUM_LEDS, 0, 0, 0);
- }
-#endif
- lb_on();
- initialized = 1;
- }
-
- res = pulse_s5_color();
- if (res)
- break;
- }
-
-#ifdef CONFIG_LIGHTBAR_POWER_RAILS
- if (initialized)
- /* Suggest that the lightbar power rails can be shut down. */
- lb_power(0);
-#endif
- lb_off();
- if (!res)
- WAIT_OR_RET(-1);
- return res;
-}
-
-/* The AP is going to poke at the lightbar directly, so we don't want the EC
- * messing with it. We'll just sit here and ignore all other messages until
- * we're told to continue (or until we think the AP is shutting down).
- */
-static uint32_t sequence_STOP(void)
-{
- uint32_t msg;
-
- do {
- msg = task_wait_event(-1);
- CPRINTS("LB %s() got pending_msg %d", __func__, pending_msg);
- } while (msg != PENDING_MSG || (
- pending_msg != LIGHTBAR_RUN &&
- pending_msg != LIGHTBAR_S0S3 &&
- pending_msg != LIGHTBAR_S3 &&
- pending_msg != LIGHTBAR_S3S5 &&
- pending_msg != LIGHTBAR_S5));
- return 0;
-}
-
-/* Telling us to run when we're already running should do nothing. */
-static uint32_t sequence_RUN(void)
-{
- return 0;
-}
-
-/* We shouldn't come here, but if we do it shouldn't hurt anything. This
- * sequence is to indicate an internal error in the lightbar logic, not an
- * error with the Chromebook itself.
- */
-static uint32_t sequence_ERROR(void)
-{
- lb_init(1);
- lb_on();
-
- lb_set_rgb(0, 255, 255, 255);
- lb_set_rgb(1, 255, 0, 255);
- lb_set_rgb(2, 0, 255, 255);
- lb_set_rgb(3, 255, 255, 255);
-
- WAIT_OR_RET(10 * SECOND);
- return 0;
-}
-
-static const struct {
- uint8_t led;
- uint8_t r, g, b;
- unsigned int delay;
-} konami[] = {
-
- {1, 0xff, 0xff, 0x00, 0},
- {2, 0xff, 0xff, 0x00, 100000},
- {1, 0x00, 0x00, 0x00, 0},
- {2, 0x00, 0x00, 0x00, 100000},
-
- {1, 0xff, 0xff, 0x00, 0},
- {2, 0xff, 0xff, 0x00, 100000},
- {1, 0x00, 0x00, 0x00, 0},
- {2, 0x00, 0x00, 0x00, 100000},
-
- {0, 0x00, 0x00, 0xff, 0},
- {3, 0x00, 0x00, 0xff, 100000},
- {0, 0x00, 0x00, 0x00, 0},
- {3, 0x00, 0x00, 0x00, 100000},
-
- {0, 0x00, 0x00, 0xff, 0},
- {3, 0x00, 0x00, 0xff, 100000},
- {0, 0x00, 0x00, 0x00, 0},
- {3, 0x00, 0x00, 0x00, 100000},
-
- {0, 0xff, 0x00, 0x00, 0},
- {1, 0xff, 0x00, 0x00, 100000},
- {0, 0x00, 0x00, 0x00, 0},
- {1, 0x00, 0x00, 0x00, 100000},
-
- {2, 0x00, 0xff, 0x00, 0},
- {3, 0x00, 0xff, 0x00, 100000},
- {2, 0x00, 0x00, 0x00, 0},
- {3, 0x00, 0x00, 0x00, 100000},
-
- {0, 0xff, 0x00, 0x00, 0},
- {1, 0xff, 0x00, 0x00, 100000},
- {0, 0x00, 0x00, 0x00, 0},
- {1, 0x00, 0x00, 0x00, 100000},
-
- {2, 0x00, 0xff, 0x00, 0},
- {3, 0x00, 0xff, 0x00, 100000},
- {2, 0x00, 0x00, 0x00, 0},
- {3, 0x00, 0x00, 0x00, 100000},
-
- {0, 0x00, 0xff, 0xff, 0},
- {2, 0x00, 0xff, 0xff, 100000},
- {0, 0x00, 0x00, 0x00, 0},
- {2, 0x00, 0x00, 0x00, 150000},
-
- {1, 0xff, 0x00, 0xff, 0},
- {3, 0xff, 0x00, 0xff, 100000},
- {1, 0x00, 0x00, 0x00, 0},
- {3, 0x00, 0x00, 0x00, 250000},
-
- {4, 0xff, 0xff, 0xff, 100000},
- {4, 0x00, 0x00, 0x00, 100000},
-
- {4, 0xff, 0xff, 0xff, 100000},
- {4, 0x00, 0x00, 0x00, 100000},
-
- {4, 0xff, 0xff, 0xff, 100000},
- {4, 0x00, 0x00, 0x00, 100000},
-
- {4, 0xff, 0xff, 0xff, 100000},
- {4, 0x00, 0x00, 0x00, 100000},
-
- {4, 0xff, 0xff, 0xff, 100000},
- {4, 0x00, 0x00, 0x00, 100000},
-
- {4, 0xff, 0xff, 0xff, 100000},
- {4, 0x00, 0x00, 0x00, 100000},
-};
-
-static uint32_t sequence_KONAMI_inner(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(konami); i++) {
- lb_set_rgb(konami[i].led,
- konami[i].r, konami[i].g, konami[i].b);
- if (konami[i].delay)
- WAIT_OR_RET(konami[i].delay);
- }
-
- return 0;
-}
-
-static uint32_t sequence_KONAMI(void)
-{
- int tmp;
- uint32_t r;
-
- /* First clear all segments */
- lb_set_rgb(NUM_LEDS, 0, 0, 0);
-
- /* Force brightness to max, then restore it */
- tmp = lb_get_brightness();
- lb_set_brightness(255);
- r = sequence_KONAMI_inner();
- lb_set_brightness(tmp);
- return r;
-}
-
-#ifdef CONFIG_LIGHTBAR_TAP_DIM_LAST_SEGMENT
-/* Returns 0.0 to 1.0 for val in [min, min + ofs] */
-static int range(int val, int min, int ofs)
-{
- if (val <= min)
- return 0;
- if (val >= min+ofs)
- return FP_SCALE;
- return (val - min) * FP_SCALE / ofs;
-}
-#endif
-
-/* Handy constant */
-#define CUT (100 / NUM_LEDS)
-
-static uint32_t sequence_TAP_inner(int dir)
-{
- enum { RED, YELLOW, GREEN } base_color;
- timestamp_t start, now;
- uint32_t elapsed_time = 0;
- int i, l, ci, max_led;
- int f_osc, f_mult;
- int gi, gr, gate[NUM_LEDS] = {0, 0, 0, 0};
- uint8_t w = 0;
-#ifdef CONFIG_LIGHTBAR_TAP_DIM_LAST_SEGMENT
- int f_min, f_delta, f_power;
-
- f_min = st.p.tap_seg_min_on * FP_SCALE / 100;
- f_delta = (st.p.tap_seg_max_on - st.p.tap_seg_min_on) * FP_SCALE / 100;
-#endif
- f_osc = st.p.tap_seg_osc * FP_SCALE / 100;
-
- get_battery_level();
-
- if (st.battery_level == 0)
- base_color = RED;
- else if (st.battery_percent > st.p.tap_pct_green)
- base_color = GREEN;
- else
- base_color = YELLOW;
-
- ci = st.p.tap_idx[base_color];
- max_led = st.battery_percent / CUT;
-
- start = get_time();
- while (1) {
- /* Enable the segments gradually */
- gi = elapsed_time / st.p.tap_gate_delay;
- gr = elapsed_time % st.p.tap_gate_delay;
- if (gi < NUM_LEDS)
- gate[gi] = FP_SCALE * gr / st.p.tap_gate_delay;
- if (gi && gi <= NUM_LEDS)
- gate[gi - 1] = FP_SCALE;
-
- for (i = 0; i < NUM_LEDS; i++) {
-
-#ifdef CONFIG_LIGHTBAR_TAP_DIM_LAST_SEGMENT
- if (max_led > i) {
- f_mult = FP_SCALE;
- } else if (max_led < i) {
- f_mult = 0;
- } else {
- switch (base_color) {
- case RED:
- f_power = range(st.battery_percent, 0,
- st.p.battery_threshold[0] - 1);
- break;
- case YELLOW:
- f_power = range(st.battery_percent,
- i * CUT, CUT - 1);
- break;
- case GREEN:
- /* green is always full on */
- f_power = FP_SCALE;
- }
- f_mult = f_min + f_power * f_delta / FP_SCALE;
- }
-#else
- if (max_led >= i)
- f_mult = FP_SCALE;
- else if (max_led < i)
- f_mult = 0;
-#endif
-
- f_mult = f_mult * gate[i] / FP_SCALE;
-
- /* Pulse when charging and not yet full */
- if (st.battery_is_charging &&
- st.battery_percent <= st.p.tap_pct_green) {
- int scale = (FP_SCALE -
- f_osc * cycle_010(w++) / FP_SCALE);
- f_mult = f_mult * scale / FP_SCALE;
- }
-
- l = dir ? i : NUM_LEDS - 1 - i;
- lb_set_rgb(l, f_mult * st.p.color[ci].r / FP_SCALE,
- f_mult * st.p.color[ci].g / FP_SCALE,
- f_mult * st.p.color[ci].b / FP_SCALE);
- }
-
- WAIT_OR_RET(st.p.tap_tick_delay);
-
- /* Return after some time has elapsed */
- now = get_time();
- elapsed_time = now.le.lo - start.le.lo;
- if (elapsed_time > st.p.tap_display_time)
- break;
- }
- return 0;
-}
-
-/* Override the tap direction for testing. -1 means ask the PD MCU. */
-static int force_dir = -1;
-
-/* Return 0 (left or none) or 1 (right) */
-static int get_tap_direction(void)
-{
- static int last_dir;
- int dir = 0;
-
- if (force_dir >= 0)
- dir = force_dir;
-#ifdef HAS_TASK_PDCMD
- else
- dir = pd_get_active_charge_port();
-#endif
- if (dir < 0)
- dir = last_dir;
- else if (dir != 1)
- dir = 0;
-
- CPRINTS("LB tap direction %d", dir);
- last_dir = dir;
- return dir;
-}
-
-static uint32_t sequence_TAP(void)
-{
- int i;
- uint32_t r;
- uint8_t br, save[NUM_LEDS][3];
- int dir;
-
- /*
- * There's a lot of unavoidable glitchiness on the AC_PRESENT interrupt
- * each time the EC boots, resulting in fights between the TAP sequence
- * and the S5S3->S3->S3S0->S0 sequences. This delay prevents the lights
- * from flickering without reducing the responsiveness to manual taps.
- */
- WAIT_OR_RET(100 * MSEC);
-
- /* Which direction should the power meter go? */
- dir = get_tap_direction();
-
-#ifdef CONFIG_LIGHTBAR_POWER_RAILS
- /* Request that the lightbar power rails be turned on. */
- if (lb_power(1)) {
- lb_set_rgb(NUM_LEDS, 0, 0, 0);
- }
-#endif
- /* First clear all segments */
- lb_set_rgb(NUM_LEDS, 0, 0, 0);
-
- lb_on();
-
- for (i = 0; i < NUM_LEDS; i++)
- lb_get_rgb(i, &save[i][0], &save[i][1], &save[i][2]);
- br = lb_get_brightness();
- lb_set_brightness(255);
-
- r = sequence_TAP_inner(dir);
-
- lb_set_brightness(br);
- for (i = 0; i < NUM_LEDS; i++)
- lb_set_rgb(i, save[i][0], save[i][1], save[i][2]);
-
-#ifdef CONFIG_LIGHTBAR_POWER_RAILS
- /* Suggest that the lightbar power rails can be shut down again. */
- lb_power(0);
-#endif
- return r;
-}
-
-/****************************************************************************/
-/* Lightbar bytecode interpreter: Lightbyte. */
-/****************************************************************************/
-
-/* When a program halts, return this. */
-#define PROGRAM_FINISHED 2
-
-static struct lightbar_program cur_prog;
-static struct lightbar_program next_prog;
-static uint8_t pc;
-
-static uint8_t led_desc[NUM_LEDS][LB_CONT_MAX][3];
-static uint32_t lb_wait_delay;
-static uint32_t lb_ramp_delay;
-/* Get one byte of data pointed to by the pc and advance
- * the pc forward.
- */
-static inline uint32_t decode_8(uint8_t *dest)
-{
- if (pc >= cur_prog.size) {
- CPRINTS("pc 0x%02x out of bounds", pc);
- return EC_RES_INVALID_PARAM;
- }
- *dest = cur_prog.data[pc++];
- return EC_SUCCESS;
-}
-
-/* Get four bytes of data pointed to by the pc and advance
- * the pc forward that amount.
- */
-static inline uint32_t decode_32(uint32_t *dest)
-{
- if (pc >= cur_prog.size - 3) {
- CPRINTS("pc 0x%02x near or out of bounds", pc);
- return EC_RES_INVALID_PARAM;
- }
- *dest = cur_prog.data[pc++] << 24;
- *dest |= cur_prog.data[pc++] << 16;
- *dest |= cur_prog.data[pc++] << 8;
- *dest |= cur_prog.data[pc++];
- return EC_SUCCESS;
-}
-
-/* ON - turn on lightbar */
-static uint32_t lightbyte_ON(void)
-{
- lb_on();
- return EC_SUCCESS;
-}
-
-/* OFF - turn off lightbar */
-static uint32_t lightbyte_OFF(void)
-{
- lb_off();
- return EC_SUCCESS;
-}
-
-/* JUMP xx - jump to immediate location
- * Changes the pc to the one-byte immediate argument.
- */
-static uint32_t lightbyte_JUMP(void)
-{
- return decode_8(&pc);
-}
-
-/* JUMP_BATTERY aa bb - switch on battery level
- * If the battery is low, changes pc to aa.
- * If the battery is high, changes pc to bb.
- * Otherwise, continues execution as normal.
- */
-static uint32_t lightbyte_JUMP_BATTERY(void)
-{
- uint8_t low_pc, high_pc;
- if (decode_8(&low_pc) != EC_SUCCESS)
- return EC_RES_INVALID_PARAM;
- if (decode_8(&high_pc) != EC_SUCCESS)
- return EC_RES_INVALID_PARAM;
-
- get_battery_level();
- if (st.battery_level == 0)
- pc = low_pc;
- else if (st.battery_level == 3)
- pc = high_pc;
-
- return EC_SUCCESS;
-}
-
-/* JUMP_IF_CHARGING xx - conditional jump to location
- * Changes the pc to xx if the device is charging.
- */
-static uint32_t lightbyte_JUMP_IF_CHARGING(void)
-{
- uint8_t charge_pc;
- if (decode_8(&charge_pc) != EC_SUCCESS)
- return EC_RES_INVALID_PARAM;
-
- if (st.battery_is_charging)
- pc = charge_pc;
-
- return EC_SUCCESS;
-}
-
-/* SET_WAIT_DELAY xx xx xx xx - set up to yield processor
- * Sets the wait delay to the given four-byte immediate, in
- * microseconds. Future WAIT instructions will wait for this
- * much time.
- */
-static uint32_t lightbyte_SET_WAIT_DELAY(void)
-{
- return decode_32(&lb_wait_delay);
-}
-
-/* SET_RAMP_DELAY xx xx xx xx - change ramp speed
- * This sets the length of time between ramp/cycle steps to
- * the four-byte immediate argument, which represents a duration
- * in milliseconds.
- */
-static uint32_t lightbyte_SET_RAMP_DELAY(void)
-{
- return decode_32(&lb_ramp_delay);
-}
-
-/* WAIT - yield processor for some time
- * Yields the processor for some amount of time set by the most
- * recent SET_WAIT_DELAY instruction.
- */
-static uint32_t lightbyte_WAIT(void)
-{
- if (lb_wait_delay != 0)
- WAIT_OR_RET(lb_wait_delay);
-
- return EC_SUCCESS;
-}
-
-/* SET_BRIGHTNESS xx
- * Sets the current brightness to the given one-byte
- * immediate argument.
- */
-static uint32_t lightbyte_SET_BRIGHTNESS(void)
-{
- uint8_t val;
- if (decode_8(&val) != EC_SUCCESS)
- return EC_RES_INVALID_PARAM;
-
- lb_set_brightness(val);
- return EC_SUCCESS;
-}
-
-/* SET_COLOR_SINGLE cc xx
- * SET_COLOR_RGB cc rr gg bb
- * Stores a color value in the led_desc structure.
- * cc is a bit-packed location to perform the action on.
- *
- * The high four bits are a bitset for which LEDs to operate on.
- * LED 0 is the lowest of the four bits.
- *
- * The next two bits are the control bits. This should be a value
- * in lb_control that is not LB_CONT_MAX, and the corresponding
- * color will be the one the action is performed on.
- *
- * The last two bits are the color bits if this instruction is
- * SET_COLOR_SINGLE. They correspond to a LB_COL value for the
- * channel to set the color for using the next immediate byte.
- * In SET_COLOR_RGB, these bits are don't-cares, as there should
- * always be three bytes that follow, which correspond to a
- * complete RGB specification.
- */
-static uint32_t lightbyte_SET_COLOR_SINGLE(void)
-{
-
- uint8_t packed_loc, led, control, color, value;
- int i;
- if (decode_8(&packed_loc) != EC_SUCCESS)
- return EC_RES_INVALID_PARAM;
- if (decode_8(&value) != EC_SUCCESS)
- return EC_RES_INVALID_PARAM;
-
- led = packed_loc >> 4;
- control = (packed_loc >> 2) & 0x3;
- color = packed_loc & 0x3;
-
- if (control >= LB_CONT_MAX)
- return EC_RES_INVALID_PARAM;
-
- for (i = 0; i < NUM_LEDS; i++)
- if (led & BIT(i))
- led_desc[i][control][color] = value;
-
- return EC_SUCCESS;
-}
-
-static uint32_t lightbyte_SET_COLOR_RGB(void)
-{
- uint8_t packed_loc, r, g, b, led, control;
- int i;
-
- /* gross */
- if (decode_8(&packed_loc) != EC_SUCCESS)
- return EC_RES_INVALID_PARAM;
- if (decode_8(&r) != EC_SUCCESS)
- return EC_RES_INVALID_PARAM;
- if (decode_8(&g) != EC_SUCCESS)
- return EC_RES_INVALID_PARAM;
- if (decode_8(&b) != EC_SUCCESS)
- return EC_RES_INVALID_PARAM;
-
- led = packed_loc >> 4;
- control = (packed_loc >> 2) & 0x3;
-
- if (control >= LB_CONT_MAX)
- return EC_RES_INVALID_PARAM;
-
- for (i = 0; i < NUM_LEDS; i++)
- if (led & BIT(i)) {
- led_desc[i][control][LB_COL_RED] = r;
- led_desc[i][control][LB_COL_GREEN] = g;
- led_desc[i][control][LB_COL_BLUE] = b;
- }
-
- return EC_SUCCESS;
-}
-
-/* GET_COLORS - take current colors and push them to the state
- * Gets the current state of the LEDs and puts them in COLOR0.
- * Good for the beginning of a program if you need to fade in.
- */
-static uint32_t lightbyte_GET_COLORS(void)
-{
- int i;
- for (i = 0; i < NUM_LEDS; i++)
- lb_get_rgb(i, &led_desc[i][LB_CONT_COLOR0][LB_COL_RED],
- &led_desc[i][LB_CONT_COLOR0][LB_COL_GREEN],
- &led_desc[i][LB_CONT_COLOR0][LB_COL_BLUE]);
-
- return EC_SUCCESS;
-}
-
-/* SWAP_COLORS - swaps beginning and end colors in state
- * Exchanges COLOR0 and COLOR1 on all LEDs.
- */
-static uint32_t lightbyte_SWAP_COLORS(void)
-{
- int i, j, tmp;
- for (i = 0; i < NUM_LEDS; i++)
- for (j = 0; j < 3; j++) {
- tmp = led_desc[i][LB_CONT_COLOR0][j];
- led_desc[i][LB_CONT_COLOR0][j] =
- led_desc[i][LB_CONT_COLOR1][j];
- led_desc[i][LB_CONT_COLOR1][j] = tmp;
- }
-
- return EC_SUCCESS;
-}
-
-static inline int get_interp_value(int led, int color, int interp)
-{
- int base = led_desc[led][LB_CONT_COLOR0][color];
- int delta = led_desc[led][LB_CONT_COLOR1][color] - base;
- return base + (delta * interp / FP_SCALE);
-}
-
-static void set_all_leds(int color)
-{
- int i, r, g, b;
- for (i = 0; i < NUM_LEDS; i++) {
- r = led_desc[i][color][LB_COL_RED];
- g = led_desc[i][color][LB_COL_GREEN];
- b = led_desc[i][color][LB_COL_BLUE];
- lb_set_rgb(i, r, g, b);
- }
-}
-
-static uint32_t ramp_all_leds(int stop_at)
-{
- int w, i, r, g, b, f;
- for (w = 0; w < stop_at; w++) {
- f = cycle_010(w);
- for (i = 0; i < NUM_LEDS; i++) {
- r = get_interp_value(i, LB_COL_RED, f);
- g = get_interp_value(i, LB_COL_GREEN, f);
- b = get_interp_value(i, LB_COL_BLUE, f);
- lb_set_rgb(i, r, g, b);
- }
- WAIT_OR_RET(lb_ramp_delay);
- }
- return EC_SUCCESS;
-}
-
-/* RAMP_ONCE - simple gradient or color set
- * If the ramp delay is set to zero, then this sets the color of
- * all LEDs to their respective COLOR1.
- * If the ramp delay is nonzero, then this sets their color to
- * their respective COLOR0, and takes them via interpolation to
- * COLOR1, with the delay time passing in between each step.
- */
-static uint32_t lightbyte_RAMP_ONCE(void)
-{
- /* special case for instantaneous set */
- if (lb_ramp_delay == 0) {
- set_all_leds(LB_CONT_COLOR1);
- return EC_SUCCESS;
- }
-
- return ramp_all_leds(128);
-}
-
-/* CYCLE_ONCE - simple cycle or color set
- * If the ramp delay is zero, then this sets the color of all LEDs
- * to their respective COLOR0.
- * If the ramp delay is nonzero, this sets the color of all LEDs
- * to COLOR0, then performs a ramp (as in RAMP_ONCE) to COLOR1,
- * and finally back to COLOR0.
- */
-static uint32_t lightbyte_CYCLE_ONCE(void)
-{
- /* special case for instantaneous set */
- if (lb_ramp_delay == 0) {
- set_all_leds(LB_CONT_COLOR0);
- return EC_SUCCESS;
- }
-
- return ramp_all_leds(256);
-}
-
-/* CYCLE - repeating cycle
- * Indefinitely ramps from COLOR0 to COLOR1, taking into
- * account the PHASE of each component of each color when
- * interpolating. (Different LEDs and different color channels
- * on a single LED can start at different places in the cycle,
- * though they will advance at the same rate.)
- *
- * If the ramp delay is zero, this instruction will error out.
- */
-static uint32_t lightbyte_CYCLE(void)
-{
- int w, i, r, g, b;
-
- /* what does it mean to cycle indefinitely with 0 delay? */
- if (lb_ramp_delay == 0)
- return EC_RES_INVALID_PARAM;
-
- for (w = 0;; w++) {
- for (i = 0; i < NUM_LEDS; i++) {
- r = get_interp_value(i, LB_COL_RED,
- cycle_010((w & 0xff) +
- led_desc[i][LB_CONT_PHASE][LB_COL_RED]));
- g = get_interp_value(i, LB_COL_GREEN,
- cycle_010((w & 0xff) +
- led_desc[i][LB_CONT_PHASE][LB_COL_GREEN]));
- b = get_interp_value(i, LB_COL_BLUE,
- cycle_010((w & 0xff) +
- led_desc[i][LB_CONT_PHASE][LB_COL_BLUE]));
- lb_set_rgb(i, r, g, b);
- }
- WAIT_OR_RET(lb_ramp_delay);
- }
- return EC_SUCCESS;
-}
-
-/* HALT - return with success
- * Show's over. Go back to what you were doing before.
- */
-static uint32_t lightbyte_HALT(void)
-{
- return PROGRAM_FINISHED;
-}
-
-#undef GET_INTERP_VALUE
-
-#define OP(NAME, BYTES, MNEMONIC) NAME,
-#include "lightbar_opcode_list.h"
-enum lightbyte_opcode {
- LIGHTBAR_OPCODE_TABLE
- MAX_OPCODE
-};
-#undef OP
-
-#define OP(NAME, BYTES, MNEMONIC) lightbyte_ ## NAME,
-#include "lightbar_opcode_list.h"
-static uint32_t (*lightbyte_dispatch[])(void) = {
- LIGHTBAR_OPCODE_TABLE
-};
-#undef OP
-
-#define OP(NAME, BYTES, MNEMONIC) MNEMONIC,
-#include "lightbar_opcode_list.h"
-static const char * const lightbyte_names[] = {
- LIGHTBAR_OPCODE_TABLE
-};
-#undef OP
-
-static uint32_t sequence_PROGRAM(void)
-{
- uint8_t saved_brightness;
- uint8_t next_inst;
- uint32_t rc;
- uint8_t old_pc;
-
- /* load next program */
- memcpy(&cur_prog, &next_prog, sizeof(struct lightbar_program));
-
- /* reset program state */
- saved_brightness = lb_get_brightness();
- pc = 0;
- memset(led_desc, 0, sizeof(led_desc));
- lb_wait_delay = 0;
- lb_ramp_delay = 0;
-
- lb_on();
- lb_set_brightness(255);
-
- /* decode-execute loop */
- for (;;) {
- old_pc = pc;
- if (decode_8(&next_inst) != EC_SUCCESS)
- return EC_RES_INVALID_PARAM;
-
- if (next_inst >= MAX_OPCODE) {
- CPRINTS("LB PROGRAM pc: 0x%02x, "
- "found invalid opcode 0x%02x",
- old_pc, next_inst);
- lb_set_brightness(saved_brightness);
- return EC_RES_INVALID_PARAM;
- } else {
- CPRINTS("LB PROGRAM pc: 0x%02x, opcode 0x%02x -> %s",
- old_pc, next_inst, lightbyte_names[next_inst]);
- rc = lightbyte_dispatch[next_inst]();
- if (rc) {
- lb_set_brightness(saved_brightness);
- return rc;
- }
- }
-
- /* yield processor in case we are stuck in a tight loop */
- WAIT_OR_RET(100);
- }
-}
-
-/****************************************************************************/
-/* The main lightbar task. It just cycles between various pretty patterns. */
-/****************************************************************************/
-
-/* Distinguish "normal" sequences from one-shot sequences */
-static inline int is_normal_sequence(enum lightbar_sequence seq)
-{
- return (seq >= LIGHTBAR_S5 && seq <= LIGHTBAR_S3S5);
-}
-
-/* Link each sequence with a command to invoke it. */
-struct lightbar_cmd_t {
- const char * const string;
- uint32_t (*sequence)(void);
-};
-
-#define LBMSG(state) { #state, sequence_##state }
-#include "lightbar_msg_list.h"
-static struct lightbar_cmd_t lightbar_cmds[] = {
- LIGHTBAR_MSG_LIST
-};
-#undef LBMSG
-
-void lightbar_task(void)
-{
- uint32_t next_seq;
-
- CPRINTS("LB task starting");
-
- lightbar_restore_state();
-
- while (1) {
- CPRINTS("LB running cur_seq %d %s. prev_seq %d %s",
- st.cur_seq, lightbar_cmds[st.cur_seq].string,
- st.prev_seq, lightbar_cmds[st.prev_seq].string);
- next_seq = lightbar_cmds[st.cur_seq].sequence();
- if (next_seq) {
- CPRINTS("LB cur_seq %d %s returned pending msg %d %s",
- st.cur_seq, lightbar_cmds[st.cur_seq].string,
- next_seq, lightbar_cmds[next_seq].string);
- if (st.cur_seq != next_seq) {
- if (is_normal_sequence(st.cur_seq))
- st.prev_seq = st.cur_seq;
- st.cur_seq = next_seq;
- }
- } else {
- CPRINTS("LB cur_seq %d %s returned value 0",
- st.cur_seq, lightbar_cmds[st.cur_seq].string);
- switch (st.cur_seq) {
- case LIGHTBAR_S5S3:
- st.cur_seq = LIGHTBAR_S3;
- break;
- case LIGHTBAR_S3S0:
- st.cur_seq = LIGHTBAR_S0;
- break;
- case LIGHTBAR_S0S3:
- st.cur_seq = LIGHTBAR_S3;
- break;
- case LIGHTBAR_S3S5:
- st.cur_seq = LIGHTBAR_S5;
- break;
- case LIGHTBAR_STOP:
- case LIGHTBAR_RUN:
- case LIGHTBAR_ERROR:
- case LIGHTBAR_KONAMI:
- case LIGHTBAR_TAP:
- case LIGHTBAR_PROGRAM:
- st.cur_seq = st.prev_seq;
- default:
- break;
- }
- }
- }
-}
-
-/* Function to request a preset sequence from the lightbar task. */
-void lightbar_sequence_f(enum lightbar_sequence num, const char *f)
-{
- if (num > 0 && num < LIGHTBAR_NUM_SEQUENCES) {
- CPRINTS("LB %s() requests %d %s", f, num,
- lightbar_cmds[num].string);
- pending_msg = num;
- task_set_event(TASK_ID_LIGHTBAR, PENDING_MSG);
- } else
- CPRINTS("LB %s() requests %d - ignored", f, num);
-}
-
-/****************************************************************************/
-/* Get notifications from other parts of the system */
-
-static uint8_t manual_suspend_control;
-
-static void lightbar_startup(void)
-{
- manual_suspend_control = 0;
- lightbar_sequence(LIGHTBAR_S5S3);
-}
-DECLARE_HOOK(HOOK_CHIPSET_STARTUP, lightbar_startup, HOOK_PRIO_DEFAULT);
-
-static void lightbar_resume(void)
-{
- if (!manual_suspend_control)
- lightbar_sequence(LIGHTBAR_S3S0);
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, lightbar_resume, HOOK_PRIO_DEFAULT);
-
-static void lightbar_suspend(void)
-{
- if (!manual_suspend_control)
- lightbar_sequence(LIGHTBAR_S0S3);
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, lightbar_suspend, HOOK_PRIO_DEFAULT);
-
-static void lightbar_shutdown(void)
-{
- lightbar_sequence(LIGHTBAR_S3S5);
-}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, lightbar_shutdown, HOOK_PRIO_DEFAULT);
-
-/****************************************************************************/
-/* Host commands via LPC bus */
-/****************************************************************************/
-
-static enum ec_status lpc_cmd_lightbar(struct host_cmd_handler_args *args)
-{
- const struct ec_params_lightbar *in = args->params;
- struct ec_response_lightbar *out = args->response;
- int rv;
-
- switch (in->cmd) {
- case LIGHTBAR_CMD_DUMP:
- lb_hc_cmd_dump(out);
- args->response_size = sizeof(out->dump);
- break;
- case LIGHTBAR_CMD_OFF:
- lb_off();
- break;
- case LIGHTBAR_CMD_ON:
- lb_on();
- break;
- case LIGHTBAR_CMD_INIT:
- lb_init(1);
- break;
- case LIGHTBAR_CMD_SET_BRIGHTNESS:
- lb_set_brightness(in->set_brightness.num);
- break;
- case LIGHTBAR_CMD_GET_BRIGHTNESS:
- out->get_brightness.num = lb_get_brightness();
- args->response_size = sizeof(out->get_brightness);
- break;
- case LIGHTBAR_CMD_SEQ:
- lightbar_sequence(in->seq.num);
- break;
- case LIGHTBAR_CMD_REG:
- lb_hc_cmd_reg(in);
- break;
- case LIGHTBAR_CMD_SET_RGB:
- lb_set_rgb(in->set_rgb.led,
- in->set_rgb.red,
- in->set_rgb.green,
- in->set_rgb.blue);
- break;
- case LIGHTBAR_CMD_GET_RGB:
- rv = lb_get_rgb(in->get_rgb.led,
- &out->get_rgb.red,
- &out->get_rgb.green,
- &out->get_rgb.blue);
- if (rv == EC_RES_SUCCESS)
- args->response_size = sizeof(out->get_rgb);
- return rv;
- case LIGHTBAR_CMD_GET_SEQ:
- out->get_seq.num = st.cur_seq;
- args->response_size = sizeof(out->get_seq);
- break;
- case LIGHTBAR_CMD_DEMO:
- demo_mode = in->demo.num ? 1 : 0;
- CPRINTS("LB_demo %d", demo_mode);
- break;
- case LIGHTBAR_CMD_GET_DEMO:
- out->get_demo.num = demo_mode;
- args->response_size = sizeof(out->get_demo);
- break;
- case LIGHTBAR_CMD_GET_PARAMS_V0:
- CPRINTS("LB_get_params_v0 not supported");
- return EC_RES_INVALID_VERSION;
- break;
- case LIGHTBAR_CMD_SET_PARAMS_V0:
- CPRINTS("LB_set_params_v0 not supported");
- return EC_RES_INVALID_VERSION;
- break;
- case LIGHTBAR_CMD_GET_PARAMS_V1:
- CPRINTS("LB_get_params_v1");
- memcpy(&out->get_params_v1, &st.p, sizeof(st.p));
- args->response_size = sizeof(out->get_params_v1);
- break;
- case LIGHTBAR_CMD_SET_PARAMS_V1:
- CPRINTS("LB_set_params_v1");
- memcpy(&st.p, &in->set_params_v1, sizeof(st.p));
- break;
- case LIGHTBAR_CMD_SET_PROGRAM:
- CPRINTS("LB_set_program");
- memcpy(&next_prog,
- &in->set_program,
- sizeof(struct lightbar_program));
- break;
- case LIGHTBAR_CMD_VERSION:
- CPRINTS("LB_version");
- out->version.num = LIGHTBAR_IMPLEMENTATION_VERSION;
- out->version.flags = LIGHTBAR_IMPLEMENTATION_FLAGS;
- args->response_size = sizeof(out->version);
- break;
- case LIGHTBAR_CMD_MANUAL_SUSPEND_CTRL:
- CPRINTS("LB_manual_suspend_ctrl");
- manual_suspend_control = in->manual_suspend_ctrl.enable;
- break;
- case LIGHTBAR_CMD_SUSPEND:
- CPRINTS("LB_suspend");
- lightbar_sequence(LIGHTBAR_S0S3);
- break;
- case LIGHTBAR_CMD_RESUME:
- CPRINTS("LB_resume");
- lightbar_sequence(LIGHTBAR_S3S0);
- break;
- case LIGHTBAR_CMD_GET_PARAMS_V2_TIMING:
- CPRINTS("LB_get_params_v2_timing");
- memcpy(&out->get_params_v2_timing,
- &st.p_v2.timing,
- sizeof(st.p_v2.timing));
- args->response_size = sizeof(out->get_params_v2_timing);
- break;
- case LIGHTBAR_CMD_SET_PARAMS_V2_TIMING:
- CPRINTS("LB_set_params_v2_timing");
- memcpy(&st.p_v2.timing,
- &in->set_v2par_timing,
- sizeof(struct lightbar_params_v2_timing));
- break;
- case LIGHTBAR_CMD_GET_PARAMS_V2_TAP:
- CPRINTS("LB_get_params_v2_tap");
- memcpy(&out->get_params_v2_tap,
- &st.p_v2.tap,
- sizeof(struct lightbar_params_v2_tap));
- args->response_size = sizeof(out->get_params_v2_tap);
- break;
- case LIGHTBAR_CMD_SET_PARAMS_V2_TAP:
- CPRINTS("LB_set_params_v2_tap");
- memcpy(&st.p_v2.tap,
- &in->set_v2par_tap,
- sizeof(struct lightbar_params_v2_tap));
- break;
- case LIGHTBAR_CMD_GET_PARAMS_V2_OSCILLATION:
- CPRINTS("LB_get_params_v2_oscillation");
- memcpy(&out->get_params_v2_osc, &st.p_v2.osc,
- sizeof(struct lightbar_params_v2_oscillation));
- args->response_size = sizeof(out->get_params_v2_osc);
- break;
- case LIGHTBAR_CMD_SET_PARAMS_V2_OSCILLATION:
- CPRINTS("LB_set_params_v2_oscillation");
- memcpy(&st.p_v2.osc,
- &in->set_v2par_osc,
- sizeof(struct lightbar_params_v2_oscillation));
- break;
- case LIGHTBAR_CMD_GET_PARAMS_V2_BRIGHTNESS:
- CPRINTS("LB_get_params_v2_brightness");
- memcpy(&out->get_params_v2_bright,
- &st.p_v2.bright,
- sizeof(struct lightbar_params_v2_brightness));
- args->response_size = sizeof(out->get_params_v2_bright);
- break;
- case LIGHTBAR_CMD_SET_PARAMS_V2_BRIGHTNESS:
- CPRINTS("LB_set_params_v2_brightness");
- memcpy(&st.p_v2.bright,
- &in->set_v2par_bright,
- sizeof(struct lightbar_params_v2_brightness));
- break;
- case LIGHTBAR_CMD_GET_PARAMS_V2_THRESHOLDS:
- CPRINTS("LB_get_params_v2_thlds");
- memcpy(&out->get_params_v2_thlds,
- &st.p_v2.thlds,
- sizeof(struct lightbar_params_v2_thresholds));
- args->response_size = sizeof(out->get_params_v2_thlds);
- break;
- case LIGHTBAR_CMD_SET_PARAMS_V2_THRESHOLDS:
- CPRINTS("LB_set_params_v2_thlds");
- memcpy(&st.p_v2.thlds,
- &in->set_v2par_thlds,
- sizeof(struct lightbar_params_v2_thresholds));
- break;
- case LIGHTBAR_CMD_GET_PARAMS_V2_COLORS:
- CPRINTS("LB_get_params_v2_colors");
- memcpy(&out->get_params_v2_colors,
- &st.p_v2.colors,
- sizeof(struct lightbar_params_v2_colors));
- args->response_size = sizeof(out->get_params_v2_colors);
- break;
- case LIGHTBAR_CMD_SET_PARAMS_V2_COLORS:
- CPRINTS("LB_set_params_v2_colors");
- memcpy(&st.p_v2.colors,
- &in->set_v2par_colors,
- sizeof(struct lightbar_params_v2_colors));
- break;
- default:
- CPRINTS("LB bad cmd 0x%x", in->cmd);
- return EC_RES_INVALID_PARAM;
- }
-
- return EC_RES_SUCCESS;
-}
-
-DECLARE_HOST_COMMAND(EC_CMD_LIGHTBAR_CMD,
- lpc_cmd_lightbar,
- EC_VER_MASK(0));
-
-/****************************************************************************/
-/* EC console commands */
-/****************************************************************************/
-
-#ifdef CONFIG_CONSOLE_CMDHELP
-static int help(const char *cmd)
-{
- ccprintf("Usage:\n");
- ccprintf(" %s - dump all regs\n", cmd);
- ccprintf(" %s off - enter standby\n", cmd);
- ccprintf(" %s on - leave standby\n", cmd);
- ccprintf(" %s init - load default vals\n", cmd);
- ccprintf(" %s brightness [NUM] - set intensity (0-ff)\n", cmd);
- ccprintf(" %s seq [NUM|SEQUENCE] - run given pattern"
- " (no arg for list)\n", cmd);
- ccprintf(" %s CTRL REG VAL - set LED controller regs\n", cmd);
- ccprintf(" %s LED RED GREEN BLUE - set color manually"
- " (LED=%d for all)\n", cmd, NUM_LEDS);
- ccprintf(" %s LED - get current LED color\n", cmd);
- ccprintf(" %s demo [0|1] - turn demo mode on & off\n", cmd);
-#ifdef LIGHTBAR_SIMULATION
- ccprintf(" %s program filename - load lightbyte program\n", cmd);
-#endif
- ccprintf(" %s version - show current version\n", cmd);
- return EC_SUCCESS;
-}
-#endif
-
-static uint8_t find_msg_by_name(const char *str)
-{
- uint8_t i;
- for (i = 0; i < LIGHTBAR_NUM_SEQUENCES; i++)
- if (!strcasecmp(str, lightbar_cmds[i].string))
- return i;
-
- return LIGHTBAR_NUM_SEQUENCES;
-}
-
-static void show_msg_names(void)
-{
- int i;
- ccprintf("Sequences:");
- for (i = 0; i < LIGHTBAR_NUM_SEQUENCES; i++)
- ccprintf(" %s", lightbar_cmds[i].string);
- ccprintf("\nCurrent = 0x%x %s\n", st.cur_seq,
- lightbar_cmds[st.cur_seq].string);
-}
-
-static int command_lightbar(int argc, char **argv)
-{
- int i;
- uint8_t num, led, r = 0, g = 0, b = 0;
- struct ec_response_lightbar out;
- char *e;
-
- if (argc == 1) { /* no args = dump 'em all */
- lb_hc_cmd_dump(&out);
- for (i = 0; i < ARRAY_SIZE(out.dump.vals); i++)
- ccprintf(" %02x %02x %02x\n",
- out.dump.vals[i].reg,
- out.dump.vals[i].ic0,
- out.dump.vals[i].ic1);
-
- return EC_SUCCESS;
- }
-
- if (!strcasecmp(argv[1], "init")) {
- lb_init(1);
- return EC_SUCCESS;
- }
-
- if (!strcasecmp(argv[1], "off")) {
- lb_off();
- return EC_SUCCESS;
- }
-
- if (!strcasecmp(argv[1], "on")) {
- lb_on();
- return EC_SUCCESS;
- }
-
- if (!strcasecmp(argv[1], "version")) {
- ccprintf("version %d flags 0x%x\n",
- LIGHTBAR_IMPLEMENTATION_VERSION,
- LIGHTBAR_IMPLEMENTATION_FLAGS);
- return EC_SUCCESS;
- }
-
- if (!strcasecmp(argv[1], "brightness")) {
- if (argc > 2) {
- num = 0xff & strtoi(argv[2], &e, 16);
- lb_set_brightness(num);
- }
- ccprintf("brightness is %02x\n", lb_get_brightness());
- return EC_SUCCESS;
- }
-
- if (!strcasecmp(argv[1], "demo")) {
- if (argc > 2) {
- if (!strcasecmp(argv[2], "on") ||
- argv[2][0] == '1')
- demo_mode = 1;
- else if (!strcasecmp(argv[2], "off") ||
- argv[2][0] == '0')
- demo_mode = 0;
- else
- return EC_ERROR_PARAM1;
- }
- ccprintf("demo mode is %s\n", demo_mode ? "on" : "off");
- return EC_SUCCESS;
- }
-
- if (!strcasecmp(argv[1], "seq")) {
- if (argc == 2) {
- show_msg_names();
- return 0;
- }
- num = 0xff & strtoi(argv[2], &e, 16);
- if (*e)
- num = find_msg_by_name(argv[2]);
- if (num >= LIGHTBAR_NUM_SEQUENCES)
- return EC_ERROR_PARAM2;
- if (argc > 3) /* for testing TAP direction */
- force_dir = strtoi(argv[3], 0, 0);
- lightbar_sequence(num);
- return EC_SUCCESS;
- }
-
-#ifdef LIGHTBAR_SIMULATION
- /* Load a program. */
- if (argc >= 3 && !strcasecmp(argv[1], "program")) {
- return lb_load_program(argv[2], &next_prog);
- }
-#endif
-
- if (argc == 4) {
- struct ec_params_lightbar in;
- in.reg.ctrl = strtoi(argv[1], &e, 16);
- in.reg.reg = strtoi(argv[2], &e, 16);
- in.reg.value = strtoi(argv[3], &e, 16);
- lb_hc_cmd_reg(&in);
- return EC_SUCCESS;
- }
-
- if (argc == 5) {
- led = strtoi(argv[1], &e, 16);
- r = strtoi(argv[2], &e, 16);
- g = strtoi(argv[3], &e, 16);
- b = strtoi(argv[4], &e, 16);
- lb_set_rgb(led, r, g, b);
- return EC_SUCCESS;
- }
-
- /* Only thing left is to try to read an LED value */
- num = strtoi(argv[1], &e, 16);
- if (!(e && *e)) {
- if (num >= NUM_LEDS) {
- for (i = 0; i < NUM_LEDS; i++) {
- lb_get_rgb(i, &r, &g, &b);
- ccprintf("%x: %02x %02x %02x\n", i, r, g, b);
- }
- } else {
- lb_get_rgb(num, &r, &g, &b);
- ccprintf("%02x %02x %02x\n", r, g, b);
- }
- return EC_SUCCESS;
- }
-
-
-#ifdef CONFIG_CONSOLE_CMDHELP
- help(argv[0]);
-#endif
-
- return EC_ERROR_INVAL;
-}
-DECLARE_CONSOLE_COMMAND(lightbar, command_lightbar,
- "[help | COMMAND [ARGS]]",
- "Get/set lightbar state");
diff --git a/common/mkbp_fifo.c b/common/mkbp_fifo.c
deleted file mode 100644
index 428d6412fc..0000000000
--- a/common/mkbp_fifo.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/* Copyright 2021 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.
- *
- * Matrix KeyBoard Protocol FIFO buffer implementation
- */
-
-#include "atomic.h"
-#include "common.h"
-#include "keyboard_config.h"
-#include "mkbp_event.h"
-#include "mkbp_fifo.h"
-#include "system.h"
-#include "task.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args)
-
-/*
- * Common FIFO depth. This needs to be big enough not to overflow if a
- * series of keys is pressed in rapid succession and the kernel is too busy
- * to read them out right away.
- *
- * RAM usage is (depth * #cols); A 16-entry FIFO will consume 16x13=208 bytes,
- * which is non-trivial but not horrible.
- */
-
-static uint32_t fifo_start; /* first entry */
-static uint32_t fifo_end; /* last entry */
-static uint32_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];
-
-/*
- * Mutex for critical sections of mkbp_fifo_add(), which is called
- * from various tasks.
- */
-K_MUTEX_DEFINE(fifo_add_mutex);
-/*
- * Mutex for critical sections of fifo_remove(), which is called from the
- * hostcmd task and from keyboard_clear_buffer().
- */
-K_MUTEX_DEFINE(fifo_remove_mutex);
-
-static int get_data_size(enum ec_mkbp_event e)
-{
- switch (e) {
- case EC_MKBP_EVENT_KEY_MATRIX:
- return KEYBOARD_COLS_MAX;
-
-#ifdef CONFIG_HOST_EVENT64
- case EC_MKBP_EVENT_HOST_EVENT64:
- return sizeof(uint64_t);
-#endif
-
- case EC_MKBP_EVENT_HOST_EVENT:
- case EC_MKBP_EVENT_BUTTON:
- case EC_MKBP_EVENT_SWITCH:
- case EC_MKBP_EVENT_SYSRQ:
- return sizeof(uint32_t);
- default:
- /* For unknown types, say it's 0. */
- return 0;
- }
-}
-
-/**
- * Pop MKBP event data from FIFO
- *
- * @return EC_SUCCESS if entry popped, EC_ERROR_UNKNOWN if FIFO is empty
- */
-static int fifo_remove(uint8_t *buffp)
-{
- int size;
-
- mutex_lock(&fifo_remove_mutex);
- if (!fifo_entries) {
- /* no entry remaining in FIFO : return last known state */
- int last = (fifo_start + FIFO_DEPTH - 1) % FIFO_DEPTH;
-
- size = get_data_size(fifo[last].event_type);
-
- memcpy(buffp, &fifo[last].data, size);
- mutex_unlock(&fifo_remove_mutex);
-
- /*
- * Bail out without changing any FIFO indices and let the
- * caller know something strange happened. The buffer will
- * will contain the last known state of the keyboard.
- */
- return EC_ERROR_UNKNOWN;
- }
-
- /* Return just the event data. */
- if (buffp) {
- size = get_data_size(fifo[fifo_start].event_type);
- /* skip over event_type. */
- memcpy(buffp, &fifo[fifo_start].data, size);
- }
-
- fifo_start = (fifo_start + 1) % FIFO_DEPTH;
- atomic_sub(&fifo_entries, 1);
- mutex_unlock(&fifo_remove_mutex);
-
- return EC_SUCCESS;
-}
-
-/*****************************************************************************/
-/* Interface */
-
-void mkbp_fifo_depth_update(uint8_t new_max_depth)
-{
- fifo_max_depth = new_max_depth;
-}
-
-
-void mkbp_fifo_clear_keyboard(void)
-{
- int i, new_fifo_entries = 0;
-
- CPRINTS("clear keyboard MKBP fifo");
-
- /*
- * Order of these locks is important to prevent deadlock since
- * mkbp_fifo_add() may call fifo_remove().
- */
- mutex_lock(&fifo_add_mutex);
- mutex_lock(&fifo_remove_mutex);
-
- /* Reset the end position */
- fifo_end = fifo_start;
-
- for (i = 0; i < fifo_entries; i++) {
- int cur = (fifo_start + i) % FIFO_DEPTH;
-
- /* Drop keyboard events */
- if (fifo[cur].event_type == EC_MKBP_EVENT_KEY_MATRIX)
- continue;
-
- /* And move other events to the front */
- memmove(&fifo[fifo_end], &fifo[cur], sizeof(fifo[cur]));
- fifo_end = (fifo_end + 1) % FIFO_DEPTH;
- ++new_fifo_entries;
- }
- fifo_entries = new_fifo_entries;
-
- mutex_unlock(&fifo_remove_mutex);
- mutex_unlock(&fifo_add_mutex);
-}
-
-void mkbp_clear_fifo(void)
-{
- int i;
-
- CPRINTS("clear MKBP fifo");
-
- /*
- * Order of these locks is important to prevent deadlock since
- * mkbp_fifo_add() may call fifo_remove().
- */
- mutex_lock(&fifo_add_mutex);
- mutex_lock(&fifo_remove_mutex);
-
- fifo_start = 0;
- fifo_end = 0;
- /* This assignment is safe since both mutexes are held. */
- fifo_entries = 0;
- for (i = 0; i < FIFO_DEPTH; i++)
- memset(&fifo[i], 0, sizeof(struct ec_response_get_next_event));
-
- mutex_unlock(&fifo_remove_mutex);
- mutex_unlock(&fifo_add_mutex);
-}
-
-test_mockable int mkbp_fifo_add(uint8_t event_type, const uint8_t *buffp)
-{
- uint8_t size;
-
- mutex_lock(&fifo_add_mutex);
- if (fifo_entries >= fifo_max_depth) {
- mutex_unlock(&fifo_add_mutex);
- CPRINTS("MKBP common FIFO depth %d reached",
- fifo_max_depth);
-
- return EC_ERROR_OVERFLOW;
- }
-
- size = get_data_size(event_type);
- fifo[fifo_end].event_type = event_type;
- memcpy(&fifo[fifo_end].data, buffp, size);
- fifo_end = (fifo_end + 1) % FIFO_DEPTH;
- atomic_add(&fifo_entries, 1);
-
- /*
- * If our event didn't generate an interrupt then the host is still
- * asleep. In this case, we don't want to queue our event, except if
- * another event just woke the host (and wake is already in progress).
- */
- if (!mkbp_send_event(event_type) && fifo_entries == 1)
- fifo_remove(NULL);
-
- mutex_unlock(&fifo_add_mutex);
- return EC_SUCCESS;
-}
-
-int mkbp_fifo_get_next_event(uint8_t *out, enum ec_mkbp_event evt)
-{
- uint8_t t = fifo[fifo_start].event_type;
- uint8_t size;
-
- if (!fifo_entries)
- return -1;
-
- /*
- * We need to peek at the next event to check that we were called with
- * the correct event.
- */
- if (t != (uint8_t)evt) {
- /*
- * We were called with the wrong event. The next element in the
- * FIFO's event type doesn't match with what we were called
- * with. Return an error that we're busy. The caller will need
- * to call us with the correct event first.
- */
- return -EC_ERROR_BUSY;
- }
-
- fifo_remove(out);
-
- /* Keep sending events if FIFO is not empty */
- if (fifo_entries)
- mkbp_send_event(fifo[fifo_start].event_type);
-
- /* Return the correct size of the data. */
- size = get_data_size(t);
- if (size)
- return size;
- else
- return -EC_ERROR_UNKNOWN;
-}
diff --git a/common/mkbp_info.c b/common/mkbp_info.c
deleted file mode 100644
index b3835367cf..0000000000
--- a/common/mkbp_info.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/* Copyright 2021 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.
- */
-
-/* MKBP info host command */
-
-#include "common.h"
-#include "console.h"
-#include "ec_commands.h"
-#include "host_command.h"
-#include "keyboard_config.h"
-#include "keyboard_mkbp.h"
-#include "keyboard_scan.h"
-#include "mkbp_input_devices.h"
-#include "util.h"
-
-static uint32_t get_supported_buttons(void)
-{
- uint32_t val = 0;
-
-#ifdef CONFIG_VOLUME_BUTTONS
- val |= BIT(EC_MKBP_VOL_UP) | BIT(EC_MKBP_VOL_DOWN);
-#endif /* defined(CONFIG_VOLUME_BUTTONS) */
-
-#ifdef CONFIG_DEDICATED_RECOVERY_BUTTON
- val |= BIT(EC_MKBP_RECOVERY);
-#endif /* defined(CONFIG_DEDICATED_RECOVERY_BUTTON) */
-
-#ifdef CONFIG_POWER_BUTTON
- val |= BIT(EC_MKBP_POWER_BUTTON);
-#endif /* defined(CONFIG_POWER_BUTTON) */
-
- return val;
-}
-
-static uint32_t get_supported_switches(void)
-{
- uint32_t val = 0;
-
-#ifdef CONFIG_LID_SWITCH
- val |= BIT(EC_MKBP_LID_OPEN);
-#endif
-#ifdef CONFIG_TABLET_MODE_SWITCH
- val |= BIT(EC_MKBP_TABLET_MODE);
-#endif
-#ifdef CONFIG_BASE_ATTACHED_SWITCH
- val |= BIT(EC_MKBP_BASE_ATTACHED);
-#endif
-#ifdef CONFIG_FRONT_PROXIMITY_SWITCH
- val |= BIT(EC_MKBP_FRONT_PROXIMITY);
-#endif
- return val;
-}
-
-static enum ec_status mkbp_get_info(struct host_cmd_handler_args *args)
-{
- const struct ec_params_mkbp_info *p = args->params;
-
- if (args->params_size == 0 || p->info_type == EC_MKBP_INFO_KBD) {
- struct ec_response_mkbp_info *r = args->response;
-
-#ifdef CONFIG_KEYBOARD_PROTOCOL_MKBP
- /* Version 0 just returns info about the keyboard. */
- r->rows = KEYBOARD_ROWS;
- r->cols = KEYBOARD_COLS_MAX;
-#else
- r->rows = 0;
- r->cols = 0;
-#endif /* CONFIG_KEYBOARD_PROTOCOL_MKBP */
-
- /* This used to be "switches" which was previously 0. */
- r->reserved = 0;
-
- args->response_size = sizeof(struct ec_response_mkbp_info);
- } else {
- union ec_response_get_next_data *r = args->response;
-
- /* Version 1 (other than EC_MKBP_INFO_KBD) */
- switch (p->info_type) {
- case EC_MKBP_INFO_SUPPORTED:
- switch (p->event_type) {
- case EC_MKBP_EVENT_BUTTON:
- r->buttons = get_supported_buttons();
- args->response_size = sizeof(r->buttons);
- break;
-
- case EC_MKBP_EVENT_SWITCH:
- r->switches = get_supported_switches();
- args->response_size = sizeof(r->switches);
- break;
-
- default:
- /* Don't care for now for other types. */
- return EC_RES_INVALID_PARAM;
- }
- break;
-
- case EC_MKBP_INFO_CURRENT:
- switch (p->event_type) {
-#ifdef HAS_TASK_KEYSCAN
- case EC_MKBP_EVENT_KEY_MATRIX:
- memcpy(r->key_matrix, keyboard_scan_get_state(),
- sizeof(r->key_matrix));
- args->response_size = sizeof(r->key_matrix);
- break;
-#endif
- case EC_MKBP_EVENT_HOST_EVENT:
- r->host_event = (uint32_t)host_get_events();
- args->response_size = sizeof(r->host_event);
- break;
-
-#ifdef CONFIG_HOST_EVENT64
- case EC_MKBP_EVENT_HOST_EVENT64:
- r->host_event64 = host_get_events();
- args->response_size = sizeof(r->host_event64);
- break;
-#endif
-
-#ifdef CONFIG_MKBP_INPUT_DEVICES
- case EC_MKBP_EVENT_BUTTON:
- r->buttons = mkbp_get_button_state();
- args->response_size = sizeof(r->buttons);
- break;
-
- case EC_MKBP_EVENT_SWITCH:
- r->switches = mkbp_get_switch_state();
- args->response_size = sizeof(r->switches);
- break;
-#endif /* CONFIG_MKBP_INPUT_DEVICES */
-
- default:
- /* Doesn't make sense for other event types. */
- return EC_RES_INVALID_PARAM;
- }
- break;
-
- default:
- /* Unsupported query. */
- return EC_RES_ERROR;
- }
- }
- return EC_RES_SUCCESS;
-}
-
-DECLARE_HOST_COMMAND(EC_CMD_MKBP_INFO, mkbp_get_info,
- EC_VER_MASK(0) | EC_VER_MASK(1));
diff --git a/common/mkbp_input_devices.c b/common/mkbp_input_devices.c
deleted file mode 100644
index e058c9d320..0000000000
--- a/common/mkbp_input_devices.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/* Copyright 2021 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.
- */
-
-/* Input devices using Matrix Keyboard Protocol [MKBP] events for Chrome EC */
-
-#include "base_state.h"
-#include "button.h"
-#include "console.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "keyboard_mkbp.h"
-#include "keyboard_scan.h"
-#include "lid_switch.h"
-#include "mkbp_event.h"
-#include "mkbp_fifo.h"
-#include "mkbp_input_devices.h"
-#include "power_button.h"
-#include "tablet_mode.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args)
-
-/* Buttons and switch state. */
-static uint32_t mkbp_button_state;
-static uint32_t mkbp_switch_state;
-
-static bool mkbp_init_done;
-
-uint32_t mkbp_get_switch_state(void)
-{
- return mkbp_switch_state;
-};
-
-uint32_t mkbp_get_button_state(void)
-{
- return mkbp_button_state;
-};
-
-void mkbp_button_update(enum keyboard_button_type button, int is_pressed)
-{
- switch (button) {
- case KEYBOARD_BUTTON_POWER:
- mkbp_button_state &= ~BIT(EC_MKBP_POWER_BUTTON);
- mkbp_button_state |= (is_pressed << EC_MKBP_POWER_BUTTON);
- break;
-
- case KEYBOARD_BUTTON_VOLUME_UP:
- mkbp_button_state &= ~BIT(EC_MKBP_VOL_UP);
- mkbp_button_state |= (is_pressed << EC_MKBP_VOL_UP);
- break;
-
- case KEYBOARD_BUTTON_VOLUME_DOWN:
- mkbp_button_state &= ~BIT(EC_MKBP_VOL_DOWN);
- mkbp_button_state |= (is_pressed << EC_MKBP_VOL_DOWN);
- break;
-
- case KEYBOARD_BUTTON_RECOVERY:
- mkbp_button_state &= ~BIT(EC_MKBP_RECOVERY);
- mkbp_button_state |= (is_pressed << EC_MKBP_RECOVERY);
- break;
-
- default:
- /* ignored. */
- return;
- }
-
- CPRINTS("mkbp buttons: %x", mkbp_button_state);
-
- mkbp_fifo_add(EC_MKBP_EVENT_BUTTON,
- (const uint8_t *)&mkbp_button_state);
-};
-
-void mkbp_update_switches(uint32_t sw, int state)
-{
- mkbp_switch_state &= ~BIT(sw);
- mkbp_switch_state |= (!!state << sw);
-
- CPRINTS("mkbp switches: %x", mkbp_switch_state);
-
- /*
- * Only inform AP mkbp changes when all switches initialized, in case
- * of the middle states causing the weird behaviour in the AP side,
- * especially when sysjumped while AP up.
- */
- if (mkbp_init_done)
- mkbp_fifo_add(EC_MKBP_EVENT_SWITCH,
- (const uint8_t *)&mkbp_switch_state);
-}
-
-
-/*****************************************************************************/
-/* Hooks */
-
-#ifdef CONFIG_POWER_BUTTON
-/**
- * Handle power button changing state.
- */
-static void keyboard_power_button(void)
-{
- mkbp_button_update(KEYBOARD_BUTTON_POWER,
- power_button_is_pressed());
-}
-DECLARE_HOOK(HOOK_POWER_BUTTON_CHANGE, keyboard_power_button,
- HOOK_PRIO_DEFAULT);
-#endif /* defined(CONFIG_POWER_BUTTON) */
-
-#ifdef CONFIG_LID_SWITCH
-/**
- * Handle lid changing state.
- */
-static void mkbp_lid_change(void)
-{
- mkbp_update_switches(EC_MKBP_LID_OPEN, lid_is_open());
-}
-DECLARE_HOOK(HOOK_LID_CHANGE, mkbp_lid_change, HOOK_PRIO_LAST);
-DECLARE_HOOK(HOOK_INIT, mkbp_lid_change, HOOK_PRIO_INIT_LID+1);
-#endif
-
-#ifdef CONFIG_TABLET_MODE_SWITCH
-static void mkbp_tablet_mode_change(void)
-{
- mkbp_update_switches(EC_MKBP_TABLET_MODE, tablet_get_mode());
-}
-DECLARE_HOOK(HOOK_TABLET_MODE_CHANGE, mkbp_tablet_mode_change, HOOK_PRIO_LAST);
-DECLARE_HOOK(HOOK_INIT, mkbp_tablet_mode_change, HOOK_PRIO_INIT_LID+1);
-#endif
-
-#ifdef CONFIG_BASE_ATTACHED_SWITCH
-static void mkbp_base_attached_change(void)
-{
- mkbp_update_switches(EC_MKBP_BASE_ATTACHED, base_get_state());
-}
-DECLARE_HOOK(HOOK_BASE_ATTACHED_CHANGE, mkbp_base_attached_change,
- HOOK_PRIO_LAST);
-DECLARE_HOOK(HOOK_INIT, mkbp_base_attached_change, HOOK_PRIO_INIT_LID+1);
-#endif
-
-static void mkbp_report_switch_on_init(void)
-{
- /* All switches initialized, report switch state to AP */
- mkbp_init_done = true;
- mkbp_fifo_add(EC_MKBP_EVENT_SWITCH,
- (const uint8_t *)&mkbp_switch_state);
-}
-DECLARE_HOOK(HOOK_INIT, mkbp_report_switch_on_init, HOOK_PRIO_LAST);
-
-#ifdef CONFIG_EMULATED_SYSRQ
-void host_send_sysrq(uint8_t key)
-{
- uint32_t value = key;
-
- mkbp_fifo_add(EC_MKBP_EVENT_SYSRQ, (const uint8_t *)&value);
-}
-#endif
-
-/*****************************************************************************/
-/* Events */
-
-static int mkbp_button_get_next_event(uint8_t *out)
-{
- return mkbp_fifo_get_next_event(out, EC_MKBP_EVENT_BUTTON);
-}
-DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_BUTTON, mkbp_button_get_next_event);
-
-static int switch_get_next_event(uint8_t *out)
-{
- return mkbp_fifo_get_next_event(out, EC_MKBP_EVENT_SWITCH);
-}
-DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_SWITCH, switch_get_next_event);
-
-#ifdef CONFIG_EMULATED_SYSRQ
-static int sysrq_get_next_event(uint8_t *out)
-{
- return mkbp_fifo_get_next_event(out, EC_MKBP_EVENT_SYSRQ);
-}
-DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_SYSRQ, sysrq_get_next_event);
-#endif
-
-/************************ Keyboard press simulation ************************/
-#ifndef HAS_TASK_KEYSCAN
-/* Keys simulated-pressed */
-static uint8_t __bss_slow simulated_key[KEYBOARD_COLS_MAX];
-uint8_t keyboard_cols = KEYBOARD_COLS_MAX;
-
-/* For boards without a keyscan task, try and simulate keyboard presses. */
-static void simulate_key(int row, int col, int pressed)
-{
- if ((simulated_key[col] & BIT(row)) == ((pressed ? 1 : 0) << row))
- return; /* No change */
-
- simulated_key[col] &= ~BIT(row);
- if (pressed)
- simulated_key[col] |= BIT(row);
-
- mkbp_fifo_add((uint8_t)EC_MKBP_EVENT_KEY_MATRIX, simulated_key);
-}
-
-static int command_mkbp_keyboard_press(int argc, char **argv)
-{
- if (argc == 1) {
- int i, j;
-
- ccputs("Simulated keys:\n");
- for (i = 0; i < keyboard_cols; ++i) {
- if (simulated_key[i] == 0)
- continue;
- for (j = 0; j < KEYBOARD_ROWS; ++j)
- if (simulated_key[i] & BIT(j))
- ccprintf("\t%d %d\n", i, j);
- }
-
- } else if (argc == 3 || argc == 4) {
- int r, c, p;
- char *e;
-
- c = strtoi(argv[1], &e, 0);
- if (*e || c < 0 || c >= keyboard_cols)
- return EC_ERROR_PARAM1;
-
- r = strtoi(argv[2], &e, 0);
- if (*e || r < 0 || r >= KEYBOARD_ROWS)
- return EC_ERROR_PARAM2;
-
- if (argc == 3) {
- /* Simulate a press and release */
- simulate_key(r, c, 1);
- simulate_key(r, c, 0);
- } else {
- p = strtoi(argv[3], &e, 0);
- if (*e || p < 0 || p > 1)
- return EC_ERROR_PARAM3;
-
- simulate_key(r, c, p);
- }
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(kbpress, command_mkbp_keyboard_press,
- "[col row [0 | 1]]",
- "Simulate keypress");
-
-#endif /* !defined(HAS_TASK_KEYSCAN) */
diff --git a/common/mock/README.md b/common/mock/README.md
deleted file mode 100644
index c7695531b6..0000000000
--- a/common/mock/README.md
+++ /dev/null
@@ -1,88 +0,0 @@
-# Common Mocks
-
-This directory holds mock implementations for use in fuzzers and tests.
-
-Each mock is given some friendly build name, like ROLLBACK or FP_SENSOR. This
-name is defined in [common/mock/build.mk](build.mk) and referenced from unit
-tests and fuzzers' `.mocklist` file.
-
-## Creating a new mock
-
-* Add the mock source to [common/mock](/common/mock) and the optional header
- file to [include/mock](/include/mock). Header files are only necessary if
- you want to expose additional [mock control](#mock-controls)
- functions/variables. See the [Design Patterns](#design-patterns) section for
- more detail on design patterns.
-* Add a new entry in [common/mock/build.mk](build.mk) that is conditioned on
- your mock's name.
-
-If a unit test or fuzzer requests this mock, the build system will set the
-variable `HAS_MOCK_<BUILD_NAME>` to `y` at build time. This variable is used to
-conditionally include the mock source in [common/mock/build.mk](build.mk).
-
-Example line from [common/mock/build.mk](build.mk):
-
-```make
-# Mocks
-mock-$(HAS_MOCK_ROLLBACK) += mock/rollback_mock.o
-```
-
-## Using a mock
-
-Unit tests and fuzzers can request a particular mock by adding an entry to their
-`.mocklist` file. The mocklist file is similar to a `.tasklist` file, where it
-is named according to the test/fuzz's name followed by `.mocklist`, like
-`fpsensor.mocklist`. The mocklist file is optional, so you may need to create
-one.
-
-Example `.mocklist`:
-
-```c
-/* Copyright 2019 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.
- */
-
- #define CONFIG_TEST_MOCK_LIST \
- MOCK(ROLLBACK) \
- MOCK(FP_SENSOR)
-```
-
-If you need additional [mock control](#mock-controls) functionality, you may
-need to include the mock's header file, which is prepended with `mock/` in the
-include line.
-
-For example, to control the return values of the rollback mock:
-
-```c
-#include "mock/rollback_mock.h"
-
-void yourfunction() {
- mock_ctrl_rollback.get_secret_fail = true;
-}
-```
-
-## Mock Controls
-
-Mocks can change their behavior by exposing "mock controls".
-
-We do this, most commonly, by exposing an additional global struct per mock that
-acts as the settings for the mock implementation. The mock user can then modify
-fields of the struct to change the mock's behavior. For example, the
-`fp_sensor_init_return` field may control what value the mocked `fp_sensor_init`
-function returns.
-
-The declaration for these controls are specified in the mock's header file,
-which resides in [include/mock](/include/mock).
-
-## Design Patterns
-
-* When creating mock controls, consider placing all your mock parameters in
- one externally facing struct, like in
- [fp_sensor_mock.h](/include/mock/fp_sensor_mock.h). The primary reason for
- this is to allow the mock to be easily used by a fuzzer (write random bytes
- into the struct with memcpy).
-* When following the above pattern, please provide a macro for resetting
- default values for this struct, like in
- [fp_sensor_mock.h](/include/mock/fp_sensor_mock.h). This allows unit tests
- to quickly reset the mock state/parameters before each unrelated unit test.
diff --git a/common/mock/battery_mock.c b/common/mock/battery_mock.c
deleted file mode 100644
index 63e94c660b..0000000000
--- a/common/mock/battery_mock.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/* Copyright 2021 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.
- */
-
-#include "battery.h"
-#include "string.h"
-
-/*****************************************************************************
- * Battery functions needed to enable CONFIG_BATTERY
- */
-static int battery_soc_value = 100;
-int board_get_battery_soc(void)
-{
- return battery_soc_value;
-}
-void set_battery_soc(int new_value)
-{
- battery_soc_value = new_value;
-}
-
-static int battery_status_value;
-int battery_status(int *status)
-{
- *status = battery_status_value;
- return EC_SUCCESS;
-}
-void set_battery_status(int new_value)
-{
- battery_status_value = new_value;
-}
-
-static int battery_serial_number_value;
-int battery_serial_number(int *serial)
-{
- *serial = battery_serial_number_value;
- return EC_SUCCESS;
-}
-void set_battery_serial_number(int new_value)
-{
- battery_serial_number_value = new_value;
-}
-
-static int battery_design_voltage_value = 5000;
-int battery_design_voltage(int *voltage)
-{
- *voltage = battery_design_voltage_value;
- return EC_SUCCESS;
-}
-void set_battery_design_voltage(int new_value)
-{
- battery_design_voltage_value = new_value;
-}
-
-static int battery_mode_value;
-int battery_get_mode(int *mode)
-{
- *mode = battery_mode_value;
- return EC_SUCCESS;
-}
-void set_battery_mode(int new_value)
-{
- battery_mode_value = new_value;
-}
-
-static int battery_soc_abs_value = 100;
-int battery_state_of_charge_abs(int *percent)
-{
- *percent = battery_soc_abs_value;
- return EC_SUCCESS;
-}
-void set_battery_soc_abs(int new_value)
-{
- battery_soc_abs_value = new_value;
-}
-
-static int battery_remaining_capacity_value = 100;
-int battery_remaining_capacity(int *capacity)
-{
- *capacity = battery_remaining_capacity_value;
- return EC_SUCCESS;
-}
-void set_battery_remaining_capacity(int new_value)
-{
- battery_remaining_capacity_value = new_value;
-}
-
-static int battery_full_charge_capacity_value = 100;
-int battery_full_charge_capacity(int *capacity)
-{
- *capacity = battery_full_charge_capacity_value;
- return EC_SUCCESS;
-}
-void set_battery_full_charge_capacity(int new_value)
-{
- battery_full_charge_capacity_value = new_value;
-}
-
-static int battery_design_capacity_value = 100;
-int battery_design_capacity(int *capacity)
-{
- *capacity = battery_design_capacity_value;
- return EC_SUCCESS;
-}
-void set_battery_design_capacity(int new_value)
-{
- battery_design_capacity_value = new_value;
-}
-
-static int battery_time_to_empty_value = 60;
-int battery_time_to_empty(int *minutes)
-{
- *minutes = battery_time_to_empty_value;
- return EC_SUCCESS;
-}
-void set_battery_time_to_empty(int new_value)
-{
- battery_time_to_empty_value = new_value;
-}
-
-static int battery_run_time_to_empty_value = 60;
-int battery_run_time_to_empty(int *minutes)
-{
- *minutes = battery_run_time_to_empty_value;
- return EC_SUCCESS;
-}
-void set_battery_run_time_to_empty(int new_value)
-{
- battery_run_time_to_empty_value = new_value;
-}
-
-static int battery_time_to_full_value;
-int battery_time_to_full(int *minutes)
-{
- *minutes = battery_time_to_full_value;
- return EC_SUCCESS;
-}
-void set_battery_time_to_full(int new_value)
-{
- battery_time_to_full_value = new_value;
-}
-
-#define MAX_DEVICE_NAME_LENGTH 40
-static char battery_device_name_value[MAX_DEVICE_NAME_LENGTH+1] = "?";
-int battery_device_name(char *dest, int size)
-{
- int i;
-
- for (i = 0; i < size && i < MAX_DEVICE_NAME_LENGTH; ++i)
- dest[i] = battery_device_name_value[i];
- for (; i < size; ++i)
- dest[i] = '\0';
- return EC_SUCCESS;
-}
-void set_battery_device_name(char *new_value)
-{
- int i;
- int size = strlen(new_value);
-
- for (i = 0; i < size && i < MAX_DEVICE_NAME_LENGTH; ++i)
- battery_device_name_value[i] = new_value[i];
- for (; i < MAX_DEVICE_NAME_LENGTH+1; ++i)
- battery_device_name_value[i] = '\0';
-}
-
-#define MAX_DEVICE_CHEMISTRY_LENGTH 40
-static char battery_device_chemistry_value[MAX_DEVICE_CHEMISTRY_LENGTH+1] = "?";
-int battery_device_chemistry(char *dest, int size)
-{
- int i;
-
- for (i = 0; i < size && i < MAX_DEVICE_CHEMISTRY_LENGTH; ++i)
- dest[i] = battery_device_chemistry_value[i];
- for (; i < size; ++i)
- dest[i] = '\0';
- return EC_SUCCESS;
-}
-void set_battery_device_chemistry(char *new_value)
-{
- int i;
- int size = strlen(new_value);
-
- for (i = 0; i < size && i < MAX_DEVICE_CHEMISTRY_LENGTH; ++i)
- battery_device_chemistry_value[i] = new_value[i];
- for (; i < MAX_DEVICE_CHEMISTRY_LENGTH+1; ++i)
- battery_device_chemistry_value[i] = '\0';
-}
-
-static int battery_current_value = 3000;
-static int battery_desired_current_value = 3000;
-static int battery_desired_voltage_value = 5000;
-static int battery_is_present_value = BP_YES;
-static int battery_temperature_value = 20;
-static int battery_voltage_value = 5000;
-void battery_get_params(struct batt_params *batt)
-{
- struct batt_params batt_new = {0};
-
- batt_new.temperature = battery_temperature_value;
- batt_new.state_of_charge = battery_soc_value;
- batt_new.voltage = battery_voltage_value;
- batt_new.current = battery_current_value;
- batt_new.desired_voltage = battery_desired_voltage_value;
- batt_new.desired_current = battery_desired_current_value;
- batt_new.remaining_capacity = battery_remaining_capacity_value;
- batt_new.full_capacity = battery_full_charge_capacity_value;
- batt_new.status = battery_status_value;
- batt_new.is_present = battery_is_present_value;
-
- memcpy(batt, &batt_new, sizeof(*batt));
-}
diff --git a/common/mock/build.mk b/common/mock/build.mk
deleted file mode 100644
index 91607b2b1e..0000000000
--- a/common/mock/build.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2019 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.
-
-# See common/mock/README.md for more information.
-
-mock-$(HAS_MOCK_BATTERY) += battery_mock.o
-mock-$(HAS_MOCK_CHARGE_MANAGER) += charge_manager_mock.o
-mock-$(HAS_MOCK_FP_SENSOR) += fp_sensor_mock.o
-mock-$(HAS_MOCK_FPSENSOR_DETECT) += fpsensor_detect_mock.o
-mock-$(HAS_MOCK_FPSENSOR_STATE) += fpsensor_state_mock.o
-mock-$(HAS_MOCK_MKBP_EVENTS) += mkbp_events_mock.o
-mock-$(HAS_MOCK_ROLLBACK) += rollback_mock.o
-mock-$(HAS_MOCK_TCPC) += tcpc_mock.o
-mock-$(HAS_MOCK_TCPM) += tcpm_mock.o
-mock-$(HAS_MOCK_TCPCI_I2C) += tcpci_i2c_mock.o
-mock-$(HAS_MOCK_TIMER) += timer_mock.o
-mock-$(HAS_MOCK_USB_MUX) += usb_mux_mock.o
-mock-$(HAS_MOCK_USB_PE_SM) += usb_pe_sm_mock.o
-mock-$(HAS_MOCK_USB_TC_SM) += usb_tc_sm_mock.o
-mock-$(HAS_MOCK_USB_PD_DPM) += usb_pd_dpm_mock.o
-mock-$(HAS_MOCK_DP_ALT_MODE) += dp_alt_mode_mock.o
-mock-$(HAS_MOCK_USB_PRL) += usb_prl_mock.o
diff --git a/common/mock/charge_manager_mock.c b/common/mock/charge_manager_mock.c
deleted file mode 100644
index 11661d2b2e..0000000000
--- a/common/mock/charge_manager_mock.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Copyright 2021 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.
- */
-
-/**
- * @file
- * @brief Mock charge_manager
- */
-
-#include <stdlib.h>
-
-#include "charge_manager.h"
-#include "common.h"
-#include "mock/charge_manager_mock.h"
-
-#ifndef TEST_BUILD
-#error "Mocks should only be in the test build."
-#endif
-
-void charge_manager_update_dualrole(int port, enum dualrole_capabilities cap)
-{
-}
-
-void charge_manager_set_ceil(int port, enum ceil_requestor requestor, int ceil)
-{
-}
-
-int charge_manager_get_selected_charge_port(void)
-{
- return 0;
-}
-
-int charge_manager_get_active_charge_port(void)
-{
- return 0;
-}
-
-int charge_manager_get_vbus_voltage(int port)
-{
- return mock_ctrl_charge_manager.vbus_voltage_mv;
-}
-
-void mock_charge_manager_set_vbus_voltage(int voltage_mv)
-{
- mock_ctrl_charge_manager.vbus_voltage_mv = voltage_mv;
-}
-
-struct mock_ctrl_charge_manager mock_ctrl_charge_manager =
-MOCK_CTRL_DEFAULT_CHARGE_MANAGER;
diff --git a/common/mock/dp_alt_mode_mock.c b/common/mock/dp_alt_mode_mock.c
deleted file mode 100644
index c489d39830..0000000000
--- a/common/mock/dp_alt_mode_mock.c
+++ /dev/null
@@ -1,35 +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.
- */
-
-/*
- * Mock for DisplayPort alternate mode support
- * Refer to VESA DisplayPort Alt Mode on USB Type-C Standard, version 2.0,
- * section 5.2
- */
-
-#include "usb_dp_alt_mode.h"
-#include "mock/dp_alt_mode_mock.h"
-
-#ifndef TEST_BUILD
-#error "Mocks should only be in the test build."
-#endif
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#else
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif
-
-void mock_dp_alt_mode_reset(void)
-{
- /* Nothing to do right now, but in the future ... */
-}
-
-void dp_init(int port)
-{
- CPRINTS("C%d: DP init", port);
-}
diff --git a/common/mock/fp_sensor_mock.c b/common/mock/fp_sensor_mock.c
deleted file mode 100644
index 363f092ff1..0000000000
--- a/common/mock/fp_sensor_mock.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/* Copyright 2019 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.
- */
-
-/**
- * @file
- * @brief Mock fpsensor private driver
- */
-
-#include <stdlib.h>
-
-#include "common.h"
-#include "fpsensor.h"
-#include "mock/fp_sensor_mock.h"
-
-#ifndef TEST_BUILD
-#error "Mocks should only be in the test build."
-#endif
-
-struct mock_ctrl_fp_sensor mock_ctrl_fp_sensor = MOCK_CTRL_DEFAULT_FP_SENSOR;
-
-int fp_sensor_init(void)
-{
- return mock_ctrl_fp_sensor.fp_sensor_init_return;
-}
-
-int fp_sensor_deinit(void)
-{
- return mock_ctrl_fp_sensor.fp_sensor_deinit_return;
-}
-
-int fp_sensor_get_info(struct ec_response_fp_info *resp)
-{
- resp->version = 0;
- return mock_ctrl_fp_sensor.fp_sensor_get_info_return;
-}
-
-void fp_sensor_low_power(void)
-{
-}
-
-void fp_sensor_configure_detect(void)
-{
-}
-
-enum finger_state fp_sensor_finger_status(void)
-{
- return mock_ctrl_fp_sensor.fp_sensor_finger_status_return;
-}
-
-int fp_sensor_acquire_image(uint8_t *image_data)
-{
- return mock_ctrl_fp_sensor.fp_sensor_acquire_image_return;
-}
-
-int fp_sensor_acquire_image_with_mode(uint8_t *image_data, int mode)
-{
- return mock_ctrl_fp_sensor.fp_sensor_acquire_image_with_mode_return;
-}
-
-int fp_finger_match(void *templ, uint32_t templ_count,
- uint8_t *image, int32_t *match_index,
- uint32_t *update_bitmap)
-{
- return mock_ctrl_fp_sensor.fp_finger_match_return;
-}
-
-int fp_enrollment_begin(void)
-{
- return mock_ctrl_fp_sensor.fp_enrollment_begin_return;
-}
-
-int fp_enrollment_finish(void *templ)
-{
- return mock_ctrl_fp_sensor.fp_enrollment_finish_return;
-}
-
-int fp_finger_enroll(uint8_t *image, int *completion)
-{
- return mock_ctrl_fp_sensor.fp_finger_enroll_return;
-}
-
-int fp_maintenance(void)
-{
- return mock_ctrl_fp_sensor.fp_maintenance_return;
-}
diff --git a/common/mock/fpsensor_detect_mock.c b/common/mock/fpsensor_detect_mock.c
deleted file mode 100644
index 6e3ca839f1..0000000000
--- a/common/mock/fpsensor_detect_mock.c
+++ /dev/null
@@ -1,28 +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.
- */
-
-#include "mock/fpsensor_detect_mock.h"
-
-#ifndef TEST_BUILD
-#error "Mocks should only be in the test build."
-#endif
-
-struct mock_ctrl_fpsensor_detect mock_ctrl_fpsensor_detect =
- MOCK_CTRL_DEFAULT_FPSENSOR_DETECT;
-
-enum fp_sensor_type get_fp_sensor_type(void)
-{
- return mock_ctrl_fpsensor_detect.get_fp_sensor_type_return;
-}
-
-enum fp_transport_type get_fp_transport_type(void)
-{
- return mock_ctrl_fpsensor_detect.get_fp_transport_type_return;
-}
-
-enum fp_sensor_spi_select get_fp_sensor_spi_select(void)
-{
- return mock_ctrl_fpsensor_detect.get_fp_sensor_spi_select_return;
-}
diff --git a/common/mock/fpsensor_state_mock.c b/common/mock/fpsensor_state_mock.c
deleted file mode 100644
index c3092fe860..0000000000
--- a/common/mock/fpsensor_state_mock.c
+++ /dev/null
@@ -1,34 +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.
- */
-
-#include <stddef.h>
-#include <string.h>
-
-#include "common.h"
-#include "ec_commands.h"
-#include "test_util.h"
-
-#ifndef TEST_BUILD
-#error "Mocks should only be in the test build."
-#endif
-
-const uint8_t default_fake_tpm_seed[] = {
- 0xd9, 0x71, 0xaf, 0xc4, 0xcd, 0x36, 0xe3, 0x60, 0xf8, 0x5a, 0xa0,
- 0xa6, 0x2c, 0xb3, 0xf5, 0xe2, 0xeb, 0xb9, 0xd8, 0x2f, 0xb5, 0x78,
- 0x5c, 0x79, 0x82, 0xce, 0x06, 0x3f, 0xcc, 0x23, 0xb9, 0xe7,
-};
-BUILD_ASSERT(sizeof(default_fake_tpm_seed) == FP_CONTEXT_TPM_BYTES);
-
-int fpsensor_state_mock_set_tpm_seed(
- const uint8_t tpm_seed[FP_CONTEXT_TPM_BYTES])
-{
- struct ec_params_fp_seed params;
-
- params.struct_version = FP_TEMPLATE_FORMAT_VERSION;
- memcpy(params.seed, tpm_seed, FP_CONTEXT_TPM_BYTES);
-
- return test_send_host_command(EC_CMD_FP_SEED, 0, &params,
- sizeof(params), NULL, 0);
-}
diff --git a/common/mock/mkbp_events_mock.c b/common/mock/mkbp_events_mock.c
deleted file mode 100644
index d42c06fdec..0000000000
--- a/common/mock/mkbp_events_mock.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Copyright 2019 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.
- */
-
-/**
- * @file
- * @brief Mock event handling for MKBP keyboard protocol
- */
-
-#include <stdint.h>
-
-#include "common.h"
-#include "mock/mkbp_events_mock.h"
-
-#ifndef TEST_BUILD
-#error "Mocks should only be in the test build."
-#endif
-
-struct mock_ctrl_mkbp_events mock_ctrl_mkbp_events =
- MOCK_CTRL_DEFAULT_MKBP_EVENTS;
-
-int mkbp_send_event(uint8_t event_type)
-{
- return mock_ctrl_mkbp_events.mkbp_send_event_return;
-}
diff --git a/common/mock/rollback_mock.c b/common/mock/rollback_mock.c
deleted file mode 100644
index 2b26d9d8d7..0000000000
--- a/common/mock/rollback_mock.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Copyright 2019 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.
- */
-
-/**
- * @file
- * @brief Mock rollback block library
- */
-
-#include <stdint.h>
-#include <string.h>
-
-#include "common.h"
-#include "compile_time_macros.h"
-#include "util.h"
-#include "mock/rollback_mock.h"
-
-#ifndef TEST_BUILD
-#error "Mocks should only be in the test build."
-#endif
-
-struct mock_ctrl_rollback mock_ctrl_rollback = MOCK_CTRL_DEFAULT_ROLLBACK;
-
-static const uint8_t fake_rollback_secret[] = {
- 0xcf, 0xe3, 0x23, 0x76, 0x35, 0x04, 0xc2, 0x0f,
- 0x0d, 0xb6, 0x02, 0xa9, 0x68, 0xba, 0x2a, 0x61,
- 0x86, 0x2a, 0x85, 0xd1, 0xca, 0x09, 0x54, 0x8a,
- 0x6b, 0xe2, 0xe3, 0x38, 0xde, 0x5d, 0x59, 0x14,
-};
-
-BUILD_ASSERT(sizeof(fake_rollback_secret) == CONFIG_ROLLBACK_SECRET_SIZE);
-
-/* Mock the rollback for unit or fuzz tests. */
-int rollback_get_secret(uint8_t *secret)
-{
- if (mock_ctrl_rollback.get_secret_fail)
- return EC_ERROR_UNKNOWN;
- memcpy(secret, fake_rollback_secret, sizeof(fake_rollback_secret));
- return EC_SUCCESS;
-}
diff --git a/common/mock/tcpc_mock.c b/common/mock/tcpc_mock.c
deleted file mode 100644
index 7097837268..0000000000
--- a/common/mock/tcpc_mock.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/* Copyright 2019 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.
- */
-/* Mock for the TCPC interface */
-
-#include "common.h"
-#include "console.h"
-#include "memory.h"
-#include "mock/tcpc_mock.h"
-#include "test_util.h"
-#include "tests/enum_strings.h"
-#include "timer.h"
-#include "usb_pd_tcpm.h"
-
-#ifndef CONFIG_COMMON_RUNTIME
-#define cprints(format, args...)
-#endif
-
-#ifndef TEST_BUILD
-#error "Mocks should only be in the test build."
-#endif
-
-/* Public API for controlling/inspecting this mock */
-struct mock_tcpc_ctrl mock_tcpc;
-
-void mock_tcpc_reset(void)
-{
- /* Reset all control values to 0. See also build assert below */
- memset(&mock_tcpc, 0, sizeof(mock_tcpc));
-
- /* Reset all last viewed variables to -1 to make them invalid */
- memset(&mock_tcpc.last, 0xff, sizeof(mock_tcpc.last));
-}
-BUILD_ASSERT(TYPEC_CC_VOLT_OPEN == 0, "Ensure Open is 0-value for memset");
-
-static int mock_init(int port)
-{
- return EC_SUCCESS;
-}
-
-static int mock_release(int port)
-{
- return EC_SUCCESS;
-}
-
-static int mock_get_cc(int port, enum tcpc_cc_voltage_status *cc1,
- enum tcpc_cc_voltage_status *cc2)
-{
- *cc1 = mock_tcpc.cc1;
- *cc2 = mock_tcpc.cc2;
- return EC_SUCCESS;
-}
-
-static bool mock_check_vbus_level(int port, enum vbus_level level)
-{
- if (level == VBUS_PRESENT)
- return mock_tcpc.vbus_level;
- else if (level == VBUS_SAFE0V || level == VBUS_REMOVED)
- return !mock_tcpc.vbus_level;
-
- /*
- * Unknown vbus_level was added, force a failure.
- * Note that TCPC drivers and pd_check_vbus_level() implementations
- * should be carefully checked on new level additions in case they
- * need updated.
- */
- ccprints("[TCPC] Unhandled Vbus check %d", level);
- TEST_ASSERT(0);
-}
-
-static int mock_select_rp_value(int port, int rp)
-{
- mock_tcpc.last.rp = rp;
-
- if (!mock_tcpc.should_print_call)
- return EC_SUCCESS;
-
- ccprints("[TCPC] Setting TCPM-side Rp to %s", from_tcpc_rp_value(rp));
-
- return EC_SUCCESS;
-}
-
-static int mock_set_cc(int port, int pull)
-{
- mock_tcpc.last.cc = pull;
-
- if (mock_tcpc.callbacks.set_cc)
- mock_tcpc.callbacks.set_cc(port, pull);
-
- if (!mock_tcpc.should_print_call)
- return EC_SUCCESS;
-
- ccprints("[TCPC] Setting TCPM-side CC to %s", from_tcpc_cc_pull(pull));
-
- return EC_SUCCESS;
-}
-
-static int mock_set_polarity(int port, enum tcpc_cc_polarity polarity)
-{
- mock_tcpc.last.polarity = polarity;
-
- if (!mock_tcpc.should_print_call)
- return EC_SUCCESS;
-
- ccprints("[TCPC] Setting TCPM-side polarity to %s",
- from_tcpc_cc_polarity(polarity));
-
- return EC_SUCCESS;
-}
-
-static int mock_set_vconn(int port, int enable)
-{
- return EC_SUCCESS;
-}
-
-static int mock_set_msg_header(int port, int power_role, int data_role)
-{
- ++mock_tcpc.num_calls_to_set_header;
-
- mock_tcpc.last.power_role = power_role;
- mock_tcpc.last.data_role = data_role;
-
- if (!mock_tcpc.should_print_call)
- return EC_SUCCESS;
-
- ccprints("[TCPC] Setting TCPM-side header to %s %s",
- from_pd_power_role(power_role),
- from_pd_data_role(data_role));
-
- return EC_SUCCESS;
-}
-
-static int mock_set_rx_enable(int port, int enable)
-{
- return EC_SUCCESS;
-}
-
-static int mock_get_message_raw(int port, uint32_t *payload, int *head)
-{
- return EC_SUCCESS;
-}
-
-static int mock_transmit(int port, enum tcpci_msg_type type,
- uint16_t header, const uint32_t *data)
-{
- return EC_SUCCESS;
-}
-
-void mock_tcpc_alert(int port)
-{
-}
-
-void mock_tcpc_discharge_vbus(int port, int enable)
-{
-}
-
-__maybe_unused static int mock_drp_toggle(int port)
-{
- /* Only set the time the first time this is called. */
- if (mock_tcpc.first_call_to_enable_auto_toggle == 0)
- mock_tcpc.first_call_to_enable_auto_toggle = get_time().val;
-
- if (!mock_tcpc.should_print_call)
- return EC_SUCCESS;
-
- ccprints("[TCPC] Enabling Auto Toggle");
-
- return EC_SUCCESS;
-}
-
-static int mock_get_chip_info(int port, int live,
- struct ec_response_pd_chip_info_v1 *info)
-{
- return EC_SUCCESS;
-}
-
-__maybe_unused static int mock_set_snk_ctrl(int port, int enable)
-{
- return EC_SUCCESS;
-}
-
-__maybe_unused static int mock_set_src_ctrl(int port, int enable)
-{
- return EC_SUCCESS;
-}
-
-__maybe_unused static int mock_enter_low_power_mode(int port)
-{
- return EC_SUCCESS;
-}
-
-int mock_set_frs_enable(int port, int enable)
-{
- return EC_SUCCESS;
-}
-
-const struct tcpm_drv mock_tcpc_driver = {
- .init = &mock_init,
- .release = &mock_release,
- .get_cc = &mock_get_cc,
- .check_vbus_level = &mock_check_vbus_level,
- .select_rp_value = &mock_select_rp_value,
- .set_cc = &mock_set_cc,
- .set_polarity = &mock_set_polarity,
- .set_vconn = &mock_set_vconn,
- .set_msg_header = &mock_set_msg_header,
- .set_rx_enable = &mock_set_rx_enable,
- .get_message_raw = &mock_get_message_raw,
- .transmit = &mock_transmit,
- .tcpc_alert = &mock_tcpc_alert,
- .tcpc_discharge_vbus = &mock_tcpc_discharge_vbus,
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- .drp_toggle = &mock_drp_toggle,
-#endif
- .get_chip_info = &mock_get_chip_info,
-#ifdef CONFIG_USB_PD_PPC
- .set_snk_ctrl = &mock_set_snk_ctrl,
- .set_src_ctrl = &mock_set_src_ctrl,
-#endif
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- .enter_low_power_mode = &mock_enter_low_power_mode,
-#endif
-#ifdef CONFIG_USB_PD_FRS_TCPC
- .set_frs_enable = &mock_set_frs_enable,
-#endif
-};
diff --git a/common/mock/tcpci_i2c_mock.c b/common/mock/tcpci_i2c_mock.c
deleted file mode 100644
index 8ec7556fca..0000000000
--- a/common/mock/tcpci_i2c_mock.c
+++ /dev/null
@@ -1,1004 +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.
- */
-
-#include "mock/tcpci_i2c_mock.h"
-#include "task.h"
-#include "tcpm/tcpci.h"
-#include "test_util.h"
-#include "timer.h"
-#include "usb_pd_tcpm.h"
-
-#ifndef TEST_BUILD
-#error "Mocks should only be in the test build."
-#endif
-
-#define BUFFER_SIZE 100
-#define VERIFY_TIMEOUT (5 * SECOND)
-
-struct tcpci_reg {
- uint8_t offset;
- uint8_t size;
- uint16_t value;
- const char *name;
-};
-
-#define TCPCI_REG(reg_name, reg_size) \
- [reg_name] = { .offset = (reg_name), .size = (reg_size), \
- .value = 0, .name = #reg_name, }
-
-static struct tcpci_reg tcpci_regs[] = {
- TCPCI_REG(TCPC_REG_VENDOR_ID, 2),
- TCPCI_REG(TCPC_REG_PRODUCT_ID, 2),
- TCPCI_REG(TCPC_REG_BCD_DEV, 2),
- TCPCI_REG(TCPC_REG_TC_REV, 2),
- TCPCI_REG(TCPC_REG_PD_REV, 2),
- TCPCI_REG(TCPC_REG_PD_INT_REV, 2),
- TCPCI_REG(TCPC_REG_ALERT, 2),
- TCPCI_REG(TCPC_REG_ALERT_MASK, 2),
- TCPCI_REG(TCPC_REG_POWER_STATUS_MASK, 1),
- TCPCI_REG(TCPC_REG_FAULT_STATUS_MASK, 1),
- TCPCI_REG(TCPC_REG_EXT_STATUS_MASK, 1),
- TCPCI_REG(TCPC_REG_ALERT_EXTENDED_MASK, 1),
- TCPCI_REG(TCPC_REG_CONFIG_STD_OUTPUT, 1),
- TCPCI_REG(TCPC_REG_TCPC_CTRL, 1),
- TCPCI_REG(TCPC_REG_ROLE_CTRL, 1),
- TCPCI_REG(TCPC_REG_FAULT_CTRL, 1),
- TCPCI_REG(TCPC_REG_POWER_CTRL, 1),
- TCPCI_REG(TCPC_REG_CC_STATUS, 1),
- TCPCI_REG(TCPC_REG_POWER_STATUS, 1),
- TCPCI_REG(TCPC_REG_FAULT_STATUS, 1),
- TCPCI_REG(TCPC_REG_EXT_STATUS, 1),
- TCPCI_REG(TCPC_REG_ALERT_EXT, 1),
- TCPCI_REG(TCPC_REG_DEV_CAP_1, 2),
- TCPCI_REG(TCPC_REG_DEV_CAP_2, 2),
- TCPCI_REG(TCPC_REG_STD_INPUT_CAP, 1),
- TCPCI_REG(TCPC_REG_STD_OUTPUT_CAP, 1),
- TCPCI_REG(TCPC_REG_CONFIG_EXT_1, 1),
- TCPCI_REG(TCPC_REG_MSG_HDR_INFO, 1),
- TCPCI_REG(TCPC_REG_RX_DETECT, 1),
- TCPCI_REG(TCPC_REG_RX_BUFFER, BUFFER_SIZE),
- TCPCI_REG(TCPC_REG_TRANSMIT, 1),
- TCPCI_REG(TCPC_REG_TX_BUFFER, BUFFER_SIZE),
- TCPCI_REG(TCPC_REG_VBUS_VOLTAGE, 2),
- TCPCI_REG(TCPC_REG_VBUS_SINK_DISCONNECT_THRESH, 2),
- TCPCI_REG(TCPC_REG_VBUS_STOP_DISCHARGE_THRESH, 2),
- TCPCI_REG(TCPC_REG_VBUS_VOLTAGE_ALARM_HI_CFG, 2),
- TCPCI_REG(TCPC_REG_VBUS_VOLTAGE_ALARM_LO_CFG, 2),
- TCPCI_REG(TCPC_REG_COMMAND, 1),
-};
-
-static uint8_t tx_buffer[BUFFER_SIZE];
-static int tx_pos = -1;
-static int tx_msg_cnt;
-static int tx_retry_cnt = -1;
-static uint8_t rx_buffer[BUFFER_SIZE];
-static int rx_pos = -1;
-
-static const char * const ctrl_msg_name[] = {
- [0] = "C-RSVD_0",
- [PD_CTRL_GOOD_CRC] = "C-GOODCRC",
- [PD_CTRL_GOTO_MIN] = "C-GOTOMIN",
- [PD_CTRL_ACCEPT] = "C-ACCEPT",
- [PD_CTRL_REJECT] = "C-REJECT",
- [PD_CTRL_PING] = "C-PING",
- [PD_CTRL_PS_RDY] = "C-PSRDY",
- [PD_CTRL_GET_SOURCE_CAP] = "C-GET_SRC_CAP",
- [PD_CTRL_GET_SINK_CAP] = "C-GET_SNK_CAP",
- [PD_CTRL_DR_SWAP] = "C-DR_SWAP",
- [PD_CTRL_PR_SWAP] = "C-PR_SWAP",
- [PD_CTRL_VCONN_SWAP] = "C-VCONN_SW",
- [PD_CTRL_WAIT] = "C-WAIT",
- [PD_CTRL_SOFT_RESET] = "C-SOFT-RESET",
- [14] = "C-RSVD_14",
- [15] = "C-RSVD_15",
- [PD_CTRL_NOT_SUPPORTED] = "C-NOT_SUPPORTED",
- [PD_CTRL_GET_SOURCE_CAP_EXT] = "C-GET_SRC_CAP-EXT",
- [PD_CTRL_GET_STATUS] = "C-GET-STATUS",
- [PD_CTRL_FR_SWAP] = "C-FR_SWAP",
- [PD_CTRL_GET_PPS_STATUS] = "C-GET_PPS_STATUS",
- [PD_CTRL_GET_COUNTRY_CODES] = "C-GET_COUNTRY_CODES",
-};
-
-static const char * const data_msg_name[] = {
- [0] = "D-RSVD_0",
- [PD_DATA_SOURCE_CAP] = "D-SRC_CAP",
- [PD_DATA_REQUEST] = "D-REQUEST",
- [PD_DATA_BIST] = "D-BIST",
- [PD_DATA_SINK_CAP] = "D-SNK_CAP",
- /* 5-14 Reserved for REV 2.0 */
- [PD_DATA_BATTERY_STATUS] = "D-BATTERY_STATUS",
- [PD_DATA_ALERT] = "D-ALERT",
- [PD_DATA_GET_COUNTRY_INFO] = "D-GET_COUNTRY_CODES",
- /* 8-14 Reserved for REV 3.0 */
- [PD_DATA_ENTER_USB] = "D-ENTER_USB",
- [PD_DATA_VENDOR_DEF] = "D-VDM",
-};
-
-static const char * const ext_msg_name[] = {
- [0] = "X-RSVD_0",
- [PD_EXT_SOURCE_CAP] = "X-SRC_CAP",
- [PD_EXT_STATUS] = "X-STATUS",
- [PD_EXT_GET_BATTERY_CAP] = "X-GET_BATTERY_CAP",
- [PD_EXT_GET_BATTERY_STATUS] = "X-GET_BATTERY_STATUS",
- [PD_EXT_BATTERY_CAP] = "X-BATTERY_CAP",
- [PD_EXT_GET_MANUFACTURER_INFO] = "X-GET_MFR_INFO",
- [PD_EXT_MANUFACTURER_INFO] = "X-MFR_INFO",
- [PD_EXT_SECURITY_REQUEST] = "X-SECURITY_REQ",
- [PD_EXT_SECURITY_RESPONSE] = "X-SECURITY_RESP",
- [PD_EXT_FIRMWARE_UPDATE_REQUEST] = "X-FW_UP_REQ",
- [PD_EXT_FIRMWARE_UPDATE_RESPONSE] = "X-FW_UP_RESP",
- [PD_EXT_PPS_STATUS] = "X-PPS_STATUS",
- [PD_EXT_COUNTRY_INFO] = "X-COUNTRY_INFO",
- [PD_EXT_COUNTRY_CODES] = "X-COUNTRY_CODES",
-};
-
-static const char * const rev_name[] = {
- [PD_REV10] = "1.0",
- [PD_REV20] = "2.0",
- [PD_REV30] = "3.0",
- [3] = "RSVD",
-};
-
-static const char * const drole_name[] = {
- [PD_ROLE_UFP] = "UFP",
- [PD_ROLE_DFP] = "DFP",
-};
-
-static const char * const prole_name[] = {
- [PD_ROLE_SINK] = "SNK",
- [PD_ROLE_SOURCE] = "SRC",
-};
-
-static void print_header(const char *prefix, uint16_t header)
-{
- int type = PD_HEADER_TYPE(header);
- int drole = PD_HEADER_DROLE(header);
- int rev = PD_HEADER_REV(header);
- int prole = PD_HEADER_PROLE(header);
- int id = PD_HEADER_ID(header);
- int cnt = PD_HEADER_CNT(header);
- int ext = PD_HEADER_EXT(header);
- const char *name = ext ? ext_msg_name[type]
- : cnt
- ? data_msg_name[type]
- : ctrl_msg_name[type];
-
- ccprints("%s header=0x%x [%s %s %s %s id=%d cnt=%d ext=%d]",
- prefix, header,
- name, drole_name[drole], rev_name[rev], prole_name[prole],
- id, cnt, ext);
-}
-
-static bool dead_battery(void)
-{
- return false;
-}
-
-static bool debug_accessory_indicator_supported(void)
-{
- return true;
-}
-
-static int verify_transmit(enum tcpci_msg_type want_tx_type,
- int want_tx_retry,
- enum pd_ctrl_msg_type want_ctrl_msg,
- enum pd_data_msg_type want_data_msg,
- int timeout)
-{
- uint64_t end_time = get_time().val + timeout;
-
- /*
- * Check that nothing was already transmitted. This ensures that all
- * transmits are checked, and the test stays in sync with the code
- * being tested.
- */
- TEST_EQ(tcpci_regs[TCPC_REG_TRANSMIT].value, 0, "%d");
-
- /* Now wait for the expected message to be transmitted. */
- while (get_time().val < end_time) {
- if (tcpci_regs[TCPC_REG_TRANSMIT].value != 0) {
- int tx_type = TCPC_REG_TRANSMIT_TYPE(
- tcpci_regs[TCPC_REG_TRANSMIT].value);
- int tx_retry = TCPC_REG_TRANSMIT_RETRY(
- tcpci_regs[TCPC_REG_TRANSMIT].value);
- uint16_t header = UINT16_FROM_BYTE_ARRAY_LE(
- tx_buffer, 1);
- int pd_type = PD_HEADER_TYPE(header);
- int pd_cnt = PD_HEADER_CNT(header);
-
- TEST_EQ(tx_type, want_tx_type, "%d");
- if (want_tx_retry >= 0)
- TEST_EQ(tx_retry, want_tx_retry, "%d");
-
- if (want_ctrl_msg != 0) {
- TEST_EQ(pd_type, want_ctrl_msg, "0x%x");
- TEST_EQ(pd_cnt, 0, "%d");
- }
- if (want_data_msg != 0) {
- TEST_EQ(pd_type, want_data_msg, "0x%x");
- TEST_GE(pd_cnt, 1, "%d");
- }
-
- tcpci_regs[TCPC_REG_TRANSMIT].value = 0;
- return EC_SUCCESS;
- }
- task_wait_event(5 * MSEC);
- }
- TEST_ASSERT(0);
- return EC_ERROR_UNKNOWN;
-}
-
-int verify_tcpci_transmit(enum tcpci_msg_type tx_type,
- enum pd_ctrl_msg_type ctrl_msg,
- enum pd_data_msg_type data_msg)
-{
- return verify_transmit(tx_type, -1,
- ctrl_msg, data_msg,
- VERIFY_TIMEOUT);
-}
-
-int verify_tcpci_tx_timeout(enum tcpci_msg_type tx_type,
- enum pd_ctrl_msg_type ctrl_msg,
- enum pd_data_msg_type data_msg,
- int timeout)
-{
- return verify_transmit(tx_type, -1,
- ctrl_msg, data_msg,
- timeout);
-}
-
-int verify_tcpci_tx_retry_count(enum tcpci_msg_type tx_type,
- enum pd_ctrl_msg_type ctrl_msg,
- enum pd_data_msg_type data_msg,
- int retry_count)
-{
- return verify_transmit(tx_type, retry_count,
- ctrl_msg, data_msg,
- VERIFY_TIMEOUT);
-}
-
-int verify_tcpci_tx_with_data(enum tcpci_msg_type tx_type,
- enum pd_data_msg_type data_msg,
- uint8_t *data,
- int data_bytes,
- int *msg_len,
- int timeout)
-{
- int rv;
-
- if (timeout <= 0)
- timeout = VERIFY_TIMEOUT;
-
- rv = verify_transmit(tx_type, -1,
- 0, data_msg,
- timeout);
- if (!rv) {
- TEST_NE(data, NULL, "%p");
- TEST_GE(data_bytes, tx_msg_cnt, "%d");
- memcpy(data, tx_buffer, tx_msg_cnt);
- if (msg_len)
- *msg_len = tx_msg_cnt;
- }
- return rv;
-}
-
-int verify_tcpci_possible_tx(struct possible_tx possible[],
- int possible_cnt,
- int *found_index,
- uint8_t *data,
- int data_bytes,
- int *msg_len,
- int timeout)
-{
- bool assert_on_timeout = true;
- uint64_t end_time;
-
- *found_index = -1;
-
- if (timeout <= 0) {
- timeout = VERIFY_TIMEOUT;
- assert_on_timeout = false;
- }
- end_time = get_time().val + timeout;
-
- /*
- * Check that nothing was already transmitted. This ensures that all
- * transmits are checked, and the test stays in sync with the code
- * being tested.
- */
- TEST_EQ(tcpci_regs[TCPC_REG_TRANSMIT].value, 0, "%d");
-
- /* Now wait for the expected message to be transmitted. */
- while (get_time().val < end_time) {
- if (tcpci_regs[TCPC_REG_TRANSMIT].value != 0) {
- int i;
- int tx_type = TCPC_REG_TRANSMIT_TYPE(
- tcpci_regs[TCPC_REG_TRANSMIT].value);
- uint16_t header = UINT16_FROM_BYTE_ARRAY_LE(
- tx_buffer, 1);
- int pd_type = PD_HEADER_TYPE(header);
- int pd_cnt = PD_HEADER_CNT(header);
-
- for (i = 0; i < possible_cnt; ++i) {
- int want_tx_type = possible[i].tx_type;
- int want_ctrl_msg = possible[i].ctrl_msg;
- int want_data_msg = possible[i].data_msg;
-
- if (tx_type != want_tx_type)
- continue;
-
- if (want_ctrl_msg != 0) {
- if (pd_type != want_ctrl_msg ||
- pd_cnt != 0)
- continue;
- }
- if (want_data_msg != 0) {
- if (pd_type != want_data_msg ||
- pd_cnt == 0)
- continue;
-
- if (data != NULL) {
- TEST_GE(data_bytes,
- tx_msg_cnt, "%d");
- memcpy(data, tx_buffer,
- tx_msg_cnt);
- }
- if (msg_len != NULL)
- *msg_len = tx_msg_cnt;
- }
- *found_index = i;
- tcpci_regs[TCPC_REG_TRANSMIT].value = 0;
- return EC_SUCCESS;
- }
- return EC_ERROR_UNKNOWN;
- }
- task_wait_event(5 * MSEC);
- }
- if (assert_on_timeout)
- TEST_ASSERT(0);
-
- return EC_ERROR_TIMEOUT;
-}
-
-void mock_tcpci_receive(enum tcpci_msg_type sop, uint16_t header,
- uint32_t *payload)
-{
- int i;
-
- rx_buffer[0] = 3 + (PD_HEADER_CNT(header) * 4);
- rx_buffer[1] = sop;
- rx_buffer[2] = header & 0xFF;
- rx_buffer[3] = (header >> 8) & 0xFF;
-
- if (rx_buffer[0] >= BUFFER_SIZE) {
- ccprints("ERROR: rx too large");
- return;
- }
-
- for (i = 4; i < rx_buffer[0]; i += 4) {
- rx_buffer[i] = *payload & 0xFF;
- rx_buffer[i+1] = (*payload >> 8) & 0xFF;
- rx_buffer[i+2] = (*payload >> 16) & 0xFF;
- rx_buffer[i+3] = (*payload >> 24) & 0xFF;
- payload++;
- }
-
- rx_pos = 0;
-}
-
-/*****************************************************************************
- * TCPCI register reset values
- *
- * These values are from USB Type-C Port Controller Interface Specification
- * Revision 2.0, Version 1.2,
- */
-static void tcpci_reset_register_masks(void)
-{
- /*
- * Using table 4-1 for default mask values
- */
- tcpci_regs[TCPC_REG_ALERT_MASK].value = 0x7FFF;
- tcpci_regs[TCPC_REG_POWER_STATUS_MASK].value = 0xFF;
- tcpci_regs[TCPC_REG_FAULT_STATUS_MASK].value = 0xFF;
- tcpci_regs[TCPC_REG_EXT_STATUS_MASK].value = 0x01;
- tcpci_regs[TCPC_REG_ALERT_EXTENDED_MASK].value = 0x07;
-}
-
-static void tcpci_reset_register_defaults(void)
-{
- int i;
-
- /* Default all registers to 0 and then overwrite if they are not */
- for (i = 0; i < ARRAY_SIZE(tcpci_regs); i++)
- tcpci_regs[i].value = 0;
-
- /* Type-C Release 1,3 */
- tcpci_regs[TCPC_REG_TC_REV].value = 0x0013;
- /* PD Revision 3.0 Version 1.2 */
- tcpci_regs[TCPC_REG_PD_REV].value = 0x3012;
- /* PD Interface Revision 2.0, Version 1.1 */
- tcpci_regs[TCPC_REG_PD_INT_REV].value = 0x2011;
-
- tcpci_reset_register_masks();
-
- tcpci_regs[TCPC_REG_CONFIG_STD_OUTPUT].value =
- TCPC_REG_CONFIG_STD_OUTPUT_AUDIO_CONN_N |
- TCPC_REG_CONFIG_STD_OUTPUT_DBG_ACC_CONN_N;
-
- tcpci_regs[TCPC_REG_POWER_CTRL].value =
- TCPC_REG_POWER_CTRL_VOLT_ALARM_DIS |
- TCPC_REG_POWER_CTRL_VBUS_VOL_MONITOR_DIS;
-
- tcpci_regs[TCPC_REG_FAULT_STATUS].value =
- TCPC_REG_FAULT_STATUS_ALL_REGS_RESET;
-
- tcpci_regs[TCPC_REG_DEV_CAP_1].value =
- TCPC_REG_DEV_CAP_1_SOURCE_VBUS |
- TCPC_REG_DEV_CAP_1_SINK_VBUS |
- TCPC_REG_DEV_CAP_1_PWRROLE_SRC_SNK_DRP |
- TCPC_REG_DEV_CAP_1_SRC_RESISTOR_RP_3P0_1P5_DEF;
-
- /*
- * Using table 4-17 to get the default Role Control and
- * Message Header Info register values.
- */
- switch (mock_tcpci_get_reg(TCPC_REG_DEV_CAP_1) &
- TCPC_REG_DEV_CAP_1_PWRROLE_MASK) {
- case TCPC_REG_DEV_CAP_1_PWRROLE_SRC_OR_SNK:
- case TCPC_REG_DEV_CAP_1_PWRROLE_SNK:
- case TCPC_REG_DEV_CAP_1_PWRROLE_SNK_ACC:
- tcpci_regs[TCPC_REG_ROLE_CTRL].value = 0x0A;
- tcpci_regs[TCPC_REG_MSG_HDR_INFO].value = 0x04;
- break;
-
- case TCPC_REG_DEV_CAP_1_PWRROLE_DRP:
- if (dead_battery())
- tcpci_regs[TCPC_REG_ROLE_CTRL].value = 0x0A;
- else if (debug_accessory_indicator_supported())
- tcpci_regs[TCPC_REG_ROLE_CTRL].value = 0x4A;
- else
- tcpci_regs[TCPC_REG_ROLE_CTRL].value = 0x0F;
- tcpci_regs[TCPC_REG_MSG_HDR_INFO].value = 0x04;
- break;
-
- case TCPC_REG_DEV_CAP_1_PWRROLE_SRC:
- if (!dead_battery())
- tcpci_regs[TCPC_REG_ROLE_CTRL].value = 0x05;
- tcpci_regs[TCPC_REG_MSG_HDR_INFO].value = 0x0D;
- break;
-
- case TCPC_REG_DEV_CAP_1_PWRROLE_SRC_SNK_DRP_ADPT_CBL:
- case TCPC_REG_DEV_CAP_1_PWRROLE_SRC_SNK_DRP:
- if (dead_battery())
- tcpci_regs[TCPC_REG_ROLE_CTRL].value = 0x0A;
- else if (debug_accessory_indicator_supported())
- tcpci_regs[TCPC_REG_ROLE_CTRL].value = 0x4A;
- else
- tcpci_regs[TCPC_REG_ROLE_CTRL].value = 0x0F;
- tcpci_regs[TCPC_REG_MSG_HDR_INFO].value = 0x04;
- break;
- }
-}
-/*****************************************************************************/
-
-void mock_tcpci_reset(void)
-{
- tcpci_reset_register_defaults();
-}
-
-void mock_tcpci_set_reg(int reg_offset, uint16_t value)
-{
- struct tcpci_reg *reg = tcpci_regs + reg_offset;
-
- reg->value = value;
- ccprints("TCPCI mock set %s = 0x%x", reg->name, reg->value);
-}
-
-void mock_tcpci_set_reg_bits(int reg_offset, uint16_t mask)
-{
- struct tcpci_reg *reg = tcpci_regs + reg_offset;
- uint16_t old_value = reg->value;
-
- reg->value |= mask;
- ccprints("TCPCI mock set bits %s (mask=0x%x) = 0x%x -> 0x%x",
- reg->name, mask, old_value, reg->value);
-}
-
-void mock_tcpci_clr_reg_bits(int reg_offset, uint16_t mask)
-{
- struct tcpci_reg *reg = tcpci_regs + reg_offset;
- uint16_t old_value = reg->value;
-
- reg->value &= ~mask;
- ccprints("TCPCI mock clr bits %s (mask=0x%x) = 0x%x -> 0x%x",
- reg->name, mask, old_value, reg->value);
-}
-
-uint16_t mock_tcpci_get_reg(int reg_offset)
-{
- return tcpci_regs[reg_offset].value;
-}
-
-int tcpci_i2c_xfer(int port, uint16_t addr_flags,
- const uint8_t *out, int out_size,
- uint8_t *in, int in_size, int flags)
-{
- struct tcpci_reg *reg;
-
- if (port != I2C_PORT_HOST_TCPC) {
- ccprints("ERROR: wrong I2C port %d", port);
- return EC_ERROR_UNKNOWN;
- }
- if (addr_flags != MOCK_TCPCI_I2C_ADDR_FLAGS) {
- ccprints("ERROR: wrong I2C address 0x%x", addr_flags);
- return EC_ERROR_UNKNOWN;
- }
-
- if (rx_pos > 0) {
- if (rx_pos + in_size > rx_buffer[0] + 1) {
- ccprints("ERROR: rx in_size");
- return EC_ERROR_UNKNOWN;
- }
- memcpy(in, rx_buffer + rx_pos, in_size);
- rx_pos += in_size;
- if (rx_pos == rx_buffer[0] + 1) {
- print_header("RX", UINT16_FROM_BYTE_ARRAY_LE(
- rx_buffer, 2));
- rx_pos = -1;
- }
- return EC_SUCCESS;
- }
-
- if (out_size == 0) {
- ccprints("ERROR: out_size == 0");
- return EC_ERROR_UNKNOWN;
- }
- if (tx_pos != -1) {
- if (tx_pos + out_size > BUFFER_SIZE) {
- ccprints("ERROR: tx out_size");
- return EC_ERROR_UNKNOWN;
- }
- memcpy(tx_buffer + tx_pos, out, out_size);
- tx_pos += out_size;
- tx_msg_cnt = tx_pos;
- if (tx_pos > 0 && tx_pos == tx_buffer[0] + 1) {
- print_header("TX", UINT16_FROM_BYTE_ARRAY_LE(
- tx_buffer, 1));
- tx_pos = -1;
- tx_retry_cnt = -1;
- }
- return EC_SUCCESS;
- }
- reg = tcpci_regs + *out;
- if (*out >= ARRAY_SIZE(tcpci_regs) || reg->size == 0) {
- ccprints("ERROR: unknown reg 0x%x", *out);
- return EC_ERROR_UNKNOWN;
- }
- if (reg->offset == TCPC_REG_TX_BUFFER) {
- if (tx_pos != -1) {
- ccprints("ERROR: TCPC_REG_TX_BUFFER not ready");
- return EC_ERROR_UNKNOWN;
- }
- tx_pos = 0;
- tx_msg_cnt = 0;
- if (out_size != 1) {
- ccprints("ERROR: TCPC_REG_TX_BUFFER out_size != 1");
- return EC_ERROR_UNKNOWN;
- }
- } else if (reg->offset == TCPC_REG_RX_BUFFER) {
- if (rx_pos != 0) {
- ccprints("ERROR: TCPC_REG_RX_BUFFER not ready");
- return EC_ERROR_UNKNOWN;
- }
- if (in_size > BUFFER_SIZE || in_size > rx_buffer[0]) {
- ccprints("ERROR: TCPC_REG_RX_BUFFER in_size");
- return EC_ERROR_UNKNOWN;
- }
- memcpy(in, rx_buffer, in_size);
- rx_pos += in_size;
- } else if (out_size == 1) {
- if (in_size != reg->size) {
- ccprints("ERROR: %s in_size %d != %d", reg->name,
- in_size, reg->size);
- return EC_ERROR_UNKNOWN;
- }
- if (reg->size == 1)
- in[0] = reg->value;
- else if (reg->size == 2) {
- in[0] = reg->value;
- in[1] = reg->value >> 8;
- }
- } else {
- uint16_t value = 0;
-
- if (in_size != 0) {
- ccprints("ERROR: in_size != 0");
- return EC_ERROR_UNKNOWN;
- }
- if (out_size != reg->size + 1) {
- ccprints("ERROR: out_size != %d", reg->size + 1);
- return EC_ERROR_UNKNOWN;
- }
- if (reg->size == 1)
- value = out[1];
- else if (reg->size == 2)
- value = out[1] + (out[2] << 8);
- ccprints("%s TCPCI write %s = 0x%x",
- task_get_name(task_get_current()),
- reg->name, value);
- if (reg->offset == TCPC_REG_ALERT)
- reg->value &= ~value;
- else
- reg->value = value;
- }
- return EC_SUCCESS;
-}
-DECLARE_TEST_I2C_XFER(tcpci_i2c_xfer);
-
-void tcpci_register_dump(void)
-{
- int reg;
- int cc1, cc2;
-
- ccprints("********* TCPCI Register Dump ***********");
- reg = mock_tcpci_get_reg(TCPC_REG_ALERT);
- ccprints("TCPC_REG_ALERT = 0x%08X", reg);
- if (reg) {
- if (reg & BIT(0))
- ccprints("\t0001: CC Status");
- if (reg & BIT(1))
- ccprints("\t0002: Power Status");
- if (reg & BIT(2))
- ccprints("\t0004: Received SOP* Message Status");
- if (reg & BIT(3))
- ccprints("\t0008: Received Hard Reset");
- if (reg & BIT(4))
- ccprints("\t0010: Transmit SOP* Message Failed");
- if (reg & BIT(5))
- ccprints("\t0020: Transmit SOP* Message Discarded");
- if (reg & BIT(6))
- ccprints("\t0040: Transmit SOP* Message Successful");
- if (reg & BIT(7))
- ccprints("\t0080: Vbus Voltage Alarm Hi");
- if (reg & BIT(8))
- ccprints("\t0100: Vbus Voltage Alarm Lo");
- if (reg & BIT(9))
- ccprints("\t0200: Fault");
- if (reg & BIT(10))
- ccprints("\t0400: Rx Buffer Overflow");
- if (reg & BIT(11))
- ccprints("\t0800: Vbus Sink Disconnect Detected");
- if (reg & BIT(12))
- ccprints("\t1000: Beginning SOP* Message Status");
- if (reg & BIT(13))
- ccprints("\t2000: Extended Status");
- if (reg & BIT(14))
- ccprints("\t4000: Alert Extended");
- if (reg & BIT(15))
- ccprints("\t8000: Vendor Defined Alert");
- }
-
- reg = mock_tcpci_get_reg(TCPC_REG_TCPC_CTRL);
- ccprints("TCPC_REG_TCPC_CTRL = 0x%04X", reg);
- if (reg & BIT(0))
- ccprints("\t01: Plug Orientation FLIP");
- if (reg & BIT(1))
- ccprints("\t02: BIST Test Mode");
- if (reg & (BIT(2) | BIT(3))) {
- switch ((reg >> 2) & 3) {
- case 2:
- ccprints("\t08: Enable Clock Stretching");
- break;
- case 3:
- ccprints("\t0C: Enable Clock Stretching if !Alert");
- break;
- }
- }
- if (reg & BIT(4))
- ccprints("\t10: Debug Accessory controlled by TCPM");
- if (reg & BIT(5))
- ccprints("\t20: Watchdog Timer enabled");
- if (reg & BIT(6))
- ccprints("\t40: Looking4Connection Alert enabled");
- if (reg & BIT(7))
- ccprints("\t80: SMBus PEC enabled");
-
- reg = mock_tcpci_get_reg(TCPC_REG_ROLE_CTRL);
- ccprints("TCPC_REG_ROLE_CTRL = 0x%04X", reg);
- cc1 = (reg >> 0) & 3;
- switch (cc1) {
- case 0:
- ccprints("\t00: CC1 == Ra");
- break;
- case 1:
- ccprints("\t01: CC1 == Rp");
- break;
- case 2:
- ccprints("\t02: CC1 == Rd");
- break;
- case 3:
- ccprints("\t03: CC1 == OPEN");
- break;
- }
- cc2 = (reg >> 2) & 3;
- switch (cc2) {
- case 0:
- ccprints("\t00: CC2 == Ra");
- break;
- case 1:
- ccprints("\t04: CC2 == Rp");
- break;
- case 2:
- ccprints("\t08: CC2 == Rd");
- break;
- case 3:
- ccprints("\t0C: CC2 == OPEN");
- break;
- }
- switch ((reg >> 4) & 3) {
- case 0:
- ccprints("\t00: Rp Value == default");
- break;
- case 1:
- ccprints("\t10: Rp Value == 1.5A");
- break;
- case 2:
- ccprints("\t20: Rp Value == 3A");
- break;
- }
- if (reg & BIT(6))
- ccprints("\t40: DRP");
-
- reg = mock_tcpci_get_reg(TCPC_REG_FAULT_CTRL);
- ccprints("TCPC_REG_FAULT_CTRL = 0x%04X", reg);
- if (reg & BIT(0))
- ccprints("\t01: Vconn Over Current Fault");
- if (reg & BIT(1))
- ccprints("\t02: Vbus OVP Fault");
- if (reg & BIT(2))
- ccprints("\t04: Vbus OCP Fault");
- if (reg & BIT(3))
- ccprints("\t08: Vbus Discharge Fault");
- if (reg & BIT(4))
- ccprints("\t10: Force OFF Vbus");
-
- reg = mock_tcpci_get_reg(TCPC_REG_POWER_CTRL);
- ccprints("TCPC_REG_POWER_CTRL = 0x%04X", reg);
- if (reg & BIT(0))
- ccprints("\t01: Enable Vconn");
- if (reg & BIT(1))
- ccprints("\t02: Vconn Power Supported");
- if (reg & BIT(2))
- ccprints("\t04: Force Discharge");
- if (reg & BIT(3))
- ccprints("\t08: Enable Bleed Discharge");
- if (reg & BIT(4))
- ccprints("\t10: Auto Discharge Disconnect");
- if (reg & BIT(5))
- ccprints("\t20: Disable Voltage Alarms");
- if (reg & BIT(6))
- ccprints("\t40: VBUS_VOLTAGE monitor disabled");
- if (reg & BIT(7))
- ccprints("\t80: Fast Role Swap enabled");
-
- reg = mock_tcpci_get_reg(TCPC_REG_CC_STATUS);
- ccprints("TCPC_REG_CC_STATUS = 0x%04X", reg);
- switch ((reg >> 0) & 3) {
- case 0:
- switch (cc1) {
- case 1:
- ccprints("\t00: CC1-Rp SRC.Open");
- break;
- case 2:
- ccprints("\t00: CC1-Rd SNK.Open");
- break;
- }
- break;
- case 1:
- switch (cc1) {
- case 1:
- ccprints("\t01: CC1-Rp SRC.Ra");
- break;
- case 2:
- ccprints("\t01: CC1-Rd SNK.Default");
- break;
- }
- break;
- case 2:
- switch (cc1) {
- case 1:
- ccprints("\t02: CC1-Rp SRC.Rd");
- break;
- case 2:
- ccprints("\t02: CC1-Rd SNK.Power1.5");
- break;
- }
- break;
- case 3:
- switch (cc1) {
- case 2:
- ccprints("\t03: CC1-Rd SNK.Power3.0");
- break;
- }
- break;
- }
- switch ((reg >> 2) & 3) {
- case 0:
- switch (cc2) {
- case 1:
- ccprints("\t00: CC2-Rp SRC.Open");
- break;
- case 2:
- ccprints("\t00: CC2-Rd SNK.Open");
- break;
- }
- break;
- case 1:
- switch (cc2) {
- case 1:
- ccprints("\t04: CC2-Rp SRC.Ra");
- break;
- case 2:
- ccprints("\t04: CC2-Rd SNK.Default");
- break;
- }
- break;
- case 2:
- switch (cc2) {
- case 1:
- ccprints("\t08: CC2-Rp SRC.Rd");
- break;
- case 2:
- ccprints("\t08: CC2-Rd SNK.Power1.5");
- break;
- }
- break;
- case 3:
- switch (cc2) {
- case 2:
- ccprints("\t0C: CC2-Rd SNK.Power3.0");
- break;
- }
- break;
- }
- if (reg & BIT(4))
- ccprints("\t10: Presenting Rd");
- else
- ccprints("\t00: Presenting Rp");
- if (reg & BIT(5))
- ccprints("\t20: Looking4Connection");
-
- reg = mock_tcpci_get_reg(TCPC_REG_POWER_STATUS);
- ccprints("TCPC_REG_POWER_STATUS = 0x%04X", reg);
- if (reg & BIT(0))
- ccprints("\t01: Sinking Vbus");
- if (reg & BIT(1))
- ccprints("\t02: Vconn Present");
- if (reg & BIT(2))
- ccprints("\t04: Vbus Present");
- if (reg & BIT(3))
- ccprints("\t08: Vbus Detect enabled");
- if (reg & BIT(4))
- ccprints("\t10: Sourcing Vbus");
- if (reg & BIT(5))
- ccprints("\t20: Sourcing non-default voltage");
- if (reg & BIT(6))
- ccprints("\t40: TCPC Initialization");
- if (reg & BIT(7))
- ccprints("\t80: Debug Accessory Connected");
-
- reg = mock_tcpci_get_reg(TCPC_REG_FAULT_STATUS);
- ccprints("TCPC_REG_FAULT_STATUS = 0x%04X", reg);
- if (reg & BIT(0))
- ccprints("\t01: I2C Interface Error");
- if (reg & BIT(1))
- ccprints("\t02: Vconn Over Current Fault");
- if (reg & BIT(2))
- ccprints("\t04: Vbus OVP Fault");
- if (reg & BIT(3))
- ccprints("\t08: Vbus OCP Fault");
- if (reg & BIT(4))
- ccprints("\t10: Forced Discharge Failed");
- if (reg & BIT(5))
- ccprints("\t20: Auto Discharge Failed");
- if (reg & BIT(6))
- ccprints("\t40: Force OFF Vbus");
- if (reg & BIT(7))
- ccprints("\t80: TCPCI Registers Reset2Default");
-
- reg = mock_tcpci_get_reg(TCPC_REG_EXT_STATUS);
- ccprints("TCPC_REG_EXT_STATUS = 0x%04X", reg);
- if (reg & BIT(0))
- ccprints("\t01: Vbus is at vSafe0V");
-
- reg = mock_tcpci_get_reg(TCPC_REG_ALERT_EXT);
- ccprints("TCPC_REG_ALERT_EXT = 0x%04X", reg);
- if (reg & BIT(0))
- ccprints("\t01: SNK Fast Role Swap");
- if (reg & BIT(1))
- ccprints("\t02: SRC Fast Role Swap");
- if (reg & BIT(2))
- ccprints("\t04: Timer Expired");
-
- reg = mock_tcpci_get_reg(TCPC_REG_COMMAND);
- ccprints("TCPC_REG_COMMAND = 0x%04X", reg);
- switch (reg) {
- case 0x11:
- ccprints("\t11: WakeI2C");
- break;
- case 0x22:
- ccprints("\t22: DisableVbusDetect");
- break;
- case 0x33:
- ccprints("\t33: EnableVbusDetect");
- break;
- case 0x44:
- ccprints("\t44: DisableSinkVbus");
- break;
- case 0x55:
- ccprints("\t55: SinkVbus");
- break;
- case 0x66:
- ccprints("\t66: DisableSourceVbus");
- break;
- case 0x77:
- ccprints("\t77: SourceVbusDefaultVoltage");
- break;
- case 0x88:
- ccprints("\t88: SourceVbusNondefaultVoltage");
- break;
- case 0x99:
- ccprints("\t99: Looking4Connection");
- break;
- case 0xAA:
- ccprints("\tAA: RxOneMore");
- break;
- case 0xCC:
- ccprints("\tCC: SendFRSwapSignal");
- break;
- case 0xDD:
- ccprints("\tDD: ResetTransmitBuffer");
- break;
- case 0xEE:
- ccprints("\tEE: ResetReceiveBuffer");
- break;
- case 0xFF:
- ccprints("\tFF: I2C Idle");
- break;
- }
-
- reg = mock_tcpci_get_reg(TCPC_REG_MSG_HDR_INFO);
- ccprints("TCPC_REG_MSG_HDR_INFO = 0x%04X", reg);
- if (reg & BIT(0))
- ccprints("\t01: Power Role SRC");
- else
- ccprints("\t00: Power Role SNK");
- switch ((reg >> 1) & 3) {
- case 0:
- ccprints("\t00: PD Revision 1.0");
- break;
- case 1:
- ccprints("\t02: PD Revision 2.0");
- break;
- case 2:
- ccprints("\t04: PD Revision 3.0");
- break;
- }
- if (reg & BIT(3))
- ccprints("\t08: Data Role DFP");
- else
- ccprints("\t00: Data Role UFP");
- if (reg & BIT(4))
- ccprints("\t10: Message originating from Cable Plug");
- else
- ccprints("\t00: Message originating from SRC/SNK/DRP");
-
- reg = mock_tcpci_get_reg(TCPC_REG_RX_BUFFER);
- ccprints("TCPC_REG_RX_BUFFER = 0x%04X", reg);
-
- reg = mock_tcpci_get_reg(TCPC_REG_TRANSMIT);
- ccprints("TCPC_REG_TRANSMIT = 0x%04X", reg);
- ccprints("*****************************************");
-}
diff --git a/common/mock/tcpm_mock.c b/common/mock/tcpm_mock.c
deleted file mode 100644
index 2c212cf8c9..0000000000
--- a/common/mock/tcpm_mock.c
+++ /dev/null
@@ -1,72 +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.
- */
-/* Mock for the TCPM interface */
-
-#include "common.h"
-#include "console.h"
-#include "memory.h"
-#include "mock/tcpm_mock.h"
-
-#ifndef TEST_BUILD
-#error "Mocks should only be in the test build."
-#endif
-
-struct mock_tcpm_t mock_tcpm[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/**
- * Gets the next waiting RX message.
- *
- * @param port Type-C port number
- * @param payload Pointer to location to copy payload of PD message
- * @param header The header of PD message
- *
- * @return EC_SUCCESS or error
- */
-int tcpm_dequeue_message(int port, uint32_t *payload, int *header)
-{
- if (!tcpm_has_pending_message(port))
- return EC_ERROR_BUSY;
-
- *header = mock_tcpm[port].mock_header;
- memcpy(payload, mock_tcpm[port].mock_rx_chk_buf,
- sizeof(mock_tcpm[port].mock_rx_chk_buf));
-
- return EC_SUCCESS;
-}
-
-/**
- * Returns true if the tcpm has RX messages waiting to be consumed.
- */
-int tcpm_has_pending_message(int port)
-{
- return mock_tcpm[port].mock_has_pending_message;
-}
-
-/**
- * Resets all mock TCPM ports
- */
-void mock_tcpm_reset(void)
-{
- int port;
-
- for (port = 0 ; port < CONFIG_USB_PD_PORT_MAX_COUNT ; ++port)
- mock_tcpm[port].mock_has_pending_message = 0;
-}
-
-/**
- * Sets up a message to be received, with optional data payload. If cnt==0,
- * then data can be NULL.
- */
-void mock_tcpm_rx_msg(int port, uint16_t header, int cnt, const uint32_t *data)
-{
- mock_tcpm[port].mock_header = header;
- if (cnt > 0) {
- int idx;
-
- for (idx = 0 ; (idx < cnt) && (idx < MOCK_CHK_BUF_SIZE) ; ++idx)
- mock_tcpm[port].mock_rx_chk_buf[idx] = data[idx];
- }
- mock_tcpm[port].mock_has_pending_message = 1;
-}
diff --git a/common/mock/timer_mock.c b/common/mock/timer_mock.c
deleted file mode 100644
index dc83aa24d5..0000000000
--- a/common/mock/timer_mock.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Copyright 2019 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.
- */
-
-#include "mock/timer_mock.h"
-
-#ifndef TEST_BUILD
-#error "Mocks should only be in the test build."
-#endif
-
-static timestamp_t now;
-
-void set_time(timestamp_t now_)
-{
- now = now_;
-}
-
-timestamp_t get_time(void)
-{
- return now;
-};
diff --git a/common/mock/usb_mux_mock.c b/common/mock/usb_mux_mock.c
deleted file mode 100644
index f2db5cf8bd..0000000000
--- a/common/mock/usb_mux_mock.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Copyright 2019 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.
- */
-/* Mock USB Type-C mux */
-
-#include "common.h"
-#include "console.h"
-#include "usb_mux.h"
-#include "mock/usb_mux_mock.h"
-#include "memory.h"
-
-#ifndef CONFIG_COMMON_RUNTIME
-#define cprints(format, args...)
-#endif
-
-#ifndef TEST_BUILD
-#error "Mocks should only be in the test build."
-#endif
-
-/* Public API for controlling/inspecting this mock */
-struct mock_usb_mux_ctrl mock_usb_mux;
-
-void mock_usb_mux_reset(void)
-{
- memset(&mock_usb_mux, 0, sizeof(mock_usb_mux));
-}
-
-static int mock_init(const struct usb_mux *me)
-{
- return EC_SUCCESS;
-}
-
-static int mock_set(const struct usb_mux *me, mux_state_t mux_state,
- bool *ack_required)
-{
- /* Mock does not use host command ACKs */
- *ack_required = false;
-
- mock_usb_mux.state = mux_state;
- ++mock_usb_mux.num_set_calls;
- ccprints("[MUX] Set to 0x%02x", mux_state);
-
- return EC_SUCCESS;
-}
-
-int mock_get(const struct usb_mux *me, mux_state_t *mux_state)
-{
- *mux_state = mock_usb_mux.state;
- return EC_SUCCESS;
-}
-
-static int mock_enter_low_power_mode(const struct usb_mux *me)
-{
- return EC_SUCCESS;
-}
-
-const struct usb_mux_driver mock_usb_mux_driver = {
- .init = &mock_init,
- .set = &mock_set,
- .get = &mock_get,
- .enter_low_power_mode = &mock_enter_low_power_mode,
-};
diff --git a/common/mock/usb_pd_dpm_mock.c b/common/mock/usb_pd_dpm_mock.c
deleted file mode 100644
index 8b6fbaa30e..0000000000
--- a/common/mock/usb_pd_dpm_mock.c
+++ /dev/null
@@ -1,72 +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.
- */
-
-/*
- * Mock of Device Policy Manager implementation
- * Refer to USB PD 3.0 spec, version 2.0, sections 8.2 and 8.3
- */
-
-#include "usb_pd.h"
-#include "mock/usb_pd_dpm_mock.h"
-#include "memory.h"
-#include "usb_pd_tcpm.h"
-
-#ifndef TEST_BUILD
-#error "Mocks should only be in the test build."
-#endif
-
-struct mock_dpm_port_t dpm[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-void mock_dpm_reset(void)
-{
- /* Reset all values to 0. */
- memset(dpm, 0, sizeof(dpm));
-}
-
-void dpm_init(int port)
-{
- dpm[port].mode_entry_done = false;
- dpm[port].mode_exit_request = false;
-}
-
-void dpm_vdm_acked(int port, enum tcpci_msg_type type, int vdo_count,
- uint32_t *vdm)
-{
-}
-
-void dpm_vdm_naked(int port, enum tcpci_msg_type type, uint16_t svid,
- uint8_t vdm_cmd)
-{
-}
-
-void dpm_set_mode_exit_request(int port)
-{
-}
-
-void dpm_run(int port)
-{
-}
-
-void dpm_evaluate_sink_fixed_pdo(int port, uint32_t vsafe5v_pdo)
-{
-}
-
-void dpm_add_non_pd_sink(int port)
-{
-}
-
-void dpm_remove_sink(int port)
-{
-}
-
-void dpm_remove_source(int port)
-{
-}
-
-int dpm_get_source_pdo(const uint32_t **src_pdo, const int port)
-{
- *src_pdo = pd_src_pdo;
- return pd_src_pdo_cnt;
-}
diff --git a/common/mock/usb_pe_sm_mock.c b/common/mock/usb_pe_sm_mock.c
deleted file mode 100644
index 8d1a25324b..0000000000
--- a/common/mock/usb_pe_sm_mock.c
+++ /dev/null
@@ -1,120 +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.
- */
-
-/* Mock USB PE state machine */
-
-#include "common.h"
-#include "console.h"
-#include "usb_pd.h"
-#include "usb_pe_sm.h"
-#include "mock/usb_pe_sm_mock.h"
-#include "memory.h"
-#include "usb_pd_tcpm.h"
-
-#ifndef CONFIG_COMMON_RUNTIME
-#define cprints(format, args...)
-#endif
-
-#ifndef TEST_BUILD
-#error "Mocks should only be in the test build."
-#endif
-
-struct mock_pe_port_t mock_pe_port[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-
-/**
- * Resets all mock PE ports to initial values
- */
-void mock_pe_port_reset(void)
-{
- int port;
-
- for (port = 0 ; port < CONFIG_USB_PD_PORT_MAX_COUNT ; ++port) {
- mock_pe_port[port].mock_pe_error = -1;
- /* These mock variable only get set to 1 by various functions,
- * so initialize them to 0. Tests can verify they are still 0
- * if that's part of the pass criteria.
- */
- mock_pe_port[port].mock_pe_message_received = 0;
- mock_pe_port[port].mock_pe_message_sent = 0;
- mock_pe_port[port].mock_pe_message_discarded = 0;
- mock_pe_port[port].mock_got_soft_reset = 0;
- mock_pe_port[port].mock_pe_got_hard_reset = 0;
- mock_pe_port[port].mock_pe_hard_reset_sent = 0;
- }
-}
-
-void pe_report_error(int port, enum pe_error e, enum tcpci_msg_type type)
-{
- mock_pe_port[port].mock_pe_error = e;
- mock_pe_port[port].sop = type;
-}
-
-void pe_report_discard(int port)
-{
- mock_pe_port[port].mock_pe_message_discarded = 1;
-}
-
-void pe_got_hard_reset(int port)
-{
- mock_pe_port[port].mock_pe_got_hard_reset = 1;
-}
-
-void pe_message_received(int port)
-{
- mock_pe_port[port].mock_pe_message_received = 1;
-}
-
-void pe_message_sent(int port)
-{
- mock_pe_port[port].mock_pe_message_sent = 1;
-}
-
-void pe_hard_reset_sent(int port)
-{
- mock_pe_port[port].mock_pe_hard_reset_sent = 1;
-}
-
-void pe_got_soft_reset(int port)
-{
- mock_pe_port[port].mock_got_soft_reset = 1;
-}
-
-bool pe_in_frs_mode(int port)
-{
- return false;
-}
-
-bool pe_in_local_ams(int port)
-{
- /* We will probably want to change this in the future */
- return false;
-}
-
-const uint32_t * const pd_get_src_caps(int port)
-{
- return NULL;
-}
-
-uint8_t pd_get_src_cap_cnt(int port)
-{
- return 0;
-}
-
-void pd_set_src_caps(int port, int cnt, uint32_t *src_caps)
-{
-}
-
-void pd_request_power_swap(int port)
-{}
-
-int pd_get_rev(int port, enum tcpci_msg_type type)
-{
- return IS_ENABLED(CONFIG_USB_PD_REV30) ? PD_REV30 : PD_REV20;
-}
-
-void pe_invalidate_explicit_contract(int port)
-{
-}
diff --git a/common/mock/usb_prl_mock.c b/common/mock/usb_prl_mock.c
deleted file mode 100644
index d5f4781829..0000000000
--- a/common/mock/usb_prl_mock.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/* Copyright 2019 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.
- *
- * Mock Protocol Layer module.
- */
-#include <string.h>
-#include "common.h"
-#include "usb_emsg.h"
-#include "usb_pe_sm.h"
-#include "usb_prl_sm.h"
-#include "mock/usb_prl_mock.h"
-#include "task.h"
-#include "test_util.h"
-#include "timer.h"
-#include "usb_pd_tcpm.h"
-
-#ifndef TEST_BUILD
-#error "Mocks should only be in the test build."
-#endif
-
-/* Defaults should all be 0 values. */
-struct extended_msg rx_emsg[CONFIG_USB_PD_PORT_MAX_COUNT];
-struct extended_msg tx_emsg[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-struct mock_prl_port_t {
- enum pd_ctrl_msg_type last_ctrl_msg;
- enum pd_data_msg_type last_data_msg;
- enum tcpci_msg_type last_tx_type;
- bool message_sent;
- bool message_received;
- enum pe_error error;
- enum tcpci_msg_type error_tx_type;
-};
-
-struct mock_prl_port_t mock_prl_port[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-void mock_prl_reset(void)
-{
- int port;
-
- /* Reset all values to 0. */
- memset(rx_emsg, 0, sizeof(rx_emsg));
- memset(tx_emsg, 0, sizeof(tx_emsg));
-
- memset(mock_prl_port, 0, sizeof(mock_prl_port));
-
- for (port = 0 ; port < CONFIG_USB_PD_PORT_MAX_COUNT ; ++port) {
- mock_prl_port[port].last_tx_type = TCPCI_MSG_INVALID;
- mock_prl_port[port].error_tx_type = TCPCI_MSG_INVALID;
- }
-}
-
-void prl_end_ams(int port)
-{}
-
-void prl_execute_hard_reset(int port)
-{
- mock_prl_port[port].last_ctrl_msg = 0;
- mock_prl_port[port].last_data_msg = 0;
- mock_prl_port[port].last_tx_type = TCPCI_MSG_TX_HARD_RESET;
-}
-
-enum pd_rev_type prl_get_rev(int port, enum tcpci_msg_type partner)
-{
- return PD_REV30;
-}
-
-void prl_hard_reset_complete(int port)
-{}
-
-int prl_is_running(int port)
-{
- return 1;
-}
-
-__overridable bool prl_is_busy(int port)
-{
- return false;
-}
-
-void prl_reset_soft(int port)
-{}
-
-void prl_send_ctrl_msg(int port, enum tcpci_msg_type type,
- enum pd_ctrl_msg_type msg)
-{
- mock_prl_port[port].last_ctrl_msg = msg;
- mock_prl_port[port].last_data_msg = 0;
- mock_prl_port[port].last_tx_type = type;
-}
-
-void prl_send_data_msg(int port, enum tcpci_msg_type type,
- enum pd_data_msg_type msg)
-{
- mock_prl_port[port].last_data_msg = msg;
- mock_prl_port[port].last_ctrl_msg = 0;
- mock_prl_port[port].last_tx_type = type;
-}
-
-void prl_send_ext_data_msg(int port, enum tcpci_msg_type type,
- enum pd_ext_msg_type msg)
-{}
-
-void prl_set_rev(int port, enum tcpci_msg_type partner,
- enum pd_rev_type rev)
-{}
-
-
-int mock_prl_wait_for_tx_msg(int port,
- enum tcpci_msg_type tx_type,
- enum pd_ctrl_msg_type ctrl_msg,
- enum pd_data_msg_type data_msg,
- int timeout)
-{
- uint64_t end_time = get_time().val + timeout;
-
- while (get_time().val < end_time) {
- if (mock_prl_port[port].last_tx_type != TCPCI_MSG_INVALID) {
- TEST_EQ(mock_prl_port[port].last_tx_type,
- tx_type, "%d");
- TEST_EQ(mock_prl_port[port].last_ctrl_msg,
- ctrl_msg, "%d");
- TEST_EQ(mock_prl_port[port].last_data_msg,
- data_msg, "%d");
- mock_prl_clear_last_sent_msg(port);
- return EC_SUCCESS;
- }
- task_wait_event(5 * MSEC);
- }
- /* A message of the expected type should have been sent by end_time. */
- TEST_ASSERT(0);
- return EC_ERROR_UNKNOWN;
-}
-
-enum pd_ctrl_msg_type mock_prl_get_last_sent_ctrl_msg(int port)
-{
- enum pd_ctrl_msg_type last = mock_prl_port[port].last_ctrl_msg;
-
- mock_prl_clear_last_sent_msg(port);
- return last;
-}
-
-enum pd_data_msg_type mock_prl_get_last_sent_data_msg(int port)
-{
- enum pd_data_msg_type last = mock_prl_port[port].last_data_msg;
-
- mock_prl_clear_last_sent_msg(port);
- return last;
-}
-
-void mock_prl_clear_last_sent_msg(int port)
-{
- mock_prl_port[port].last_data_msg = 0;
- mock_prl_port[port].last_ctrl_msg = 0;
- mock_prl_port[port].last_tx_type = TCPCI_MSG_INVALID;
-}
-
-timestamp_t prl_get_tcpc_tx_success_ts(int port)
-{
- return get_time();
-}
-void mock_prl_message_sent(int port)
-{
- mock_prl_port[port].message_sent = 1;
-}
-
-void mock_prl_message_received(int port)
-{
- mock_prl_port[port].message_received = 1;
-}
-
-void mock_prl_report_error(int port, enum pe_error e,
- enum tcpci_msg_type tx_type)
-{
- mock_prl_port[port].error = e;
- mock_prl_port[port].error_tx_type = tx_type;
-}
-
-void prl_run(int port, int evt, int en)
-{
- if (mock_prl_port[port].message_sent) {
- ccprints("message_sent");
- pe_message_sent(port);
- mock_prl_port[port].message_sent = 0;
- }
- if (mock_prl_port[port].message_received) {
- ccprints("message_received");
- pe_message_received(port);
- mock_prl_port[port].message_received = 0;
- }
- if (mock_prl_port[port].error_tx_type != TCPCI_MSG_INVALID) {
- ccprints("pe_error %d", mock_prl_port[port].error);
- pe_report_error(port,
- mock_prl_port[port].error,
- mock_prl_port[port].error_tx_type);
- mock_prl_port[port].error = 0;
- mock_prl_port[port].error_tx_type = TCPCI_MSG_INVALID;
- }
-}
diff --git a/common/mock/usb_tc_sm_mock.c b/common/mock/usb_tc_sm_mock.c
deleted file mode 100644
index d55def12e2..0000000000
--- a/common/mock/usb_tc_sm_mock.c
+++ /dev/null
@@ -1,214 +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.
- */
-
-/* Mock USB TC state machine */
-
-#include "common.h"
-#include "console.h"
-#include "ec_commands.h"
-#include "usb_tc_sm.h"
-#include "mock/usb_tc_sm_mock.h"
-#include "memory.h"
-
-#ifndef CONFIG_COMMON_RUNTIME
-#define cprints(format, args...)
-#endif
-
-#ifndef TEST_BUILD
-#error "Mocks should only be in the test build."
-#endif
-
-struct mock_tc_port_t mock_tc_port[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-void mock_tc_port_reset(void)
-{
- int port;
-
- for (port = 0 ; port < CONFIG_USB_PD_PORT_MAX_COUNT ; ++port) {
- mock_tc_port[port].rev = PD_REV30;
- mock_tc_port[port].pd_enable = 0;
- mock_tc_port[port].msg_tx_id = 0;
- mock_tc_port[port].msg_rx_id = 0;
- mock_tc_port[port].sop = TCPCI_MSG_INVALID;
- mock_tc_port[port].lcl_rp = TYPEC_RP_RESERVED;
- mock_tc_port[port].attached_snk = 0;
- mock_tc_port[port].attached_src = 0;
- mock_tc_port[port].vconn_src = false;
- mock_tc_port[port].data_role = PD_ROLE_UFP;
- mock_tc_port[port].power_role = PD_ROLE_SINK;
- }
-}
-
-enum pd_cable_plug tc_get_cable_plug(int port)
-{
- return PD_PLUG_FROM_DFP_UFP;
-}
-
-uint8_t tc_get_pd_enabled(int port)
-{
- return mock_tc_port[port].pd_enable;
-}
-
-void typec_select_src_collision_rp(int port, enum tcpc_rp_value rp)
-{
- mock_tc_port[port].lcl_rp = rp;
-}
-
-void typec_select_src_current_limit_rp(int port, enum tcpc_rp_value rp)
-{
-}
-
-int tc_is_attached_src(int port)
-{
- return mock_tc_port[port].attached_src;
-}
-
-int tc_is_attached_snk(int port)
-{
- return mock_tc_port[port].attached_snk;
-}
-
-void tc_prs_snk_src_assert_rp(int port)
-{
- mock_tc_port[port].attached_snk = 0;
- mock_tc_port[port].attached_src = 1;
-}
-
-void tc_prs_src_snk_assert_rd(int port)
-{
- mock_tc_port[port].attached_snk = 1;
- mock_tc_port[port].attached_src = 0;
-}
-
-int typec_update_cc(int port)
-{
- return EC_SUCCESS;
-}
-
-int tc_check_vconn_swap(int port)
-{
- return 0;
-}
-
-void tc_ctvpd_detected(int port)
-{}
-
-int tc_is_vconn_src(int port)
-{
- return mock_tc_port[port].vconn_src;
-}
-
-void tc_hard_reset_request(int port)
-{
- mock_tc_port_reset();
-}
-
-void tc_partner_dr_data(int port, int en)
-{}
-
-void tc_partner_dr_power(int port, int en)
-{}
-
-void tc_partner_unconstrainedpower(int port, int en)
-{}
-
-void tc_partner_usb_comm(int port, int en)
-{}
-
-void tc_pd_connection(int port, int en)
-{}
-
-void tc_pr_swap_complete(int port, bool success)
-{}
-
-void tc_src_power_off(int port)
-{}
-
-void tc_start_error_recovery(int port)
-{}
-
-void tc_snk_power_off(int port)
-{}
-
-void tc_request_power_swap(int port)
-{
-}
-
-enum pd_dual_role_states pd_get_dual_role(int port)
-{
- return PD_DRP_TOGGLE_ON;
-}
-
-enum pd_data_role pd_get_data_role(int port)
-{
- return mock_tc_port[port].data_role;
-}
-
-enum pd_power_role pd_get_power_role(int port)
-{
- return mock_tc_port[port].power_role;
-}
-
-enum pd_cc_states pd_get_task_cc_state(int port)
-{
- return PD_CC_NONE;
-}
-
-int pd_is_connected(int port)
-{
- return 1;
-}
-
-bool pd_is_disconnected(int port)
-{
- return false;
-}
-
-bool pd_get_partner_usb_comm_capable(int port)
-{
- return true;
-}
-
-bool pd_get_partner_dual_role_power(int port)
-{
- return true;
-}
-
-bool pd_capable(int port)
-{
- return true;
-}
-
-bool pd_waiting_on_partner_src_caps(int port)
-{
- return false;
-}
-
-void pd_set_suspend(int port, int suspend)
-{
-}
-
-void pd_set_error_recovery(int port)
-{
-}
-
-enum tcpc_cc_polarity pd_get_polarity(int port)
-{
- return POLARITY_CC1;
-}
-
-void pd_request_data_swap(int port)
-{}
-
-void pd_request_vconn_swap_off(int port)
-{}
-
-void pd_request_vconn_swap_on(int port)
-{}
-
-bool pd_alt_mode_capable(int port)
-{
- return false;
-}
diff --git a/common/motion_orientation.c b/common/motion_orientation.c
deleted file mode 100644
index 9a20ff8499..0000000000
--- a/common/motion_orientation.c
+++ /dev/null
@@ -1,37 +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.
- */
-
-/* Implement an orientation sensor. */
-
-#include "motion_orientation.h"
-
-/*
- * Orientation mode vectors, must match sequential ordering of
- * known orientations from enum motionsensor_orientation
- */
-static const intv3_t orientation_modes[] = {
- [MOTIONSENSE_ORIENTATION_LANDSCAPE] = { 0, -1, 0 },
- [MOTIONSENSE_ORIENTATION_PORTRAIT] = { 1, 0, 0 },
- [MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_PORTRAIT] = { -1, 0, 0 },
- [MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_LANDSCAPE] = { 0, 1, 0 },
-};
-
-enum motionsensor_orientation motion_orientation_remap(
- const struct motion_sensor_t *s,
- enum motionsensor_orientation orientation)
-{
- enum motionsensor_orientation rotated_orientation;
- const intv3_t *orientation_v;
- intv3_t rotated_orientation_v;
-
- if (orientation == MOTIONSENSE_ORIENTATION_UNKNOWN)
- return MOTIONSENSE_ORIENTATION_UNKNOWN;
-
- orientation_v = &orientation_modes[orientation];
- rotate(*orientation_v, *s->rot_standard_ref, rotated_orientation_v);
- rotated_orientation = ((2 * rotated_orientation_v[1] +
- rotated_orientation_v[0] + 4) % 5);
- return rotated_orientation;
-}
diff --git a/common/newton_fit.c b/common/newton_fit.c
deleted file mode 100644
index ae81a45f07..0000000000
--- a/common/newton_fit.c
+++ /dev/null
@@ -1,186 +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.
- */
-
-#include "common.h"
-#include "console.h"
-#include "newton_fit.h"
-#include "math.h"
-#include "math_util.h"
-#include <string.h>
-
-#define CPRINTS(fmt, args...) cprints(CC_MOTION_SENSE, fmt, ##args)
-
-static fp_t distance_squared(fpv3_t a, fpv3_t b)
-{
- fpv3_t delta;
-
- fpv3_init(delta, a[X] - b[X], a[Y] - b[Y], a[Z] - b[Z]);
- return fpv3_dot(delta, delta);
-}
-
-static fp_t compute_error(struct newton_fit *fit, fpv3_t center)
-{
- fp_t error = FLOAT_TO_FP(0.0f);
- struct queue_iterator it;
- struct newton_fit_orientation *_it;
-
- for (queue_begin(fit->orientations, &it); it.ptr != NULL;
- queue_next(fit->orientations, &it)) {
- fp_t e;
-
- _it = (struct newton_fit_orientation *)it.ptr;
- e = FLOAT_TO_FP(1.0f) -
- distance_squared(_it->orientation, center);
- error += fp_mul(e, e);
- }
-
- return error;
-}
-
-static bool is_ready_to_compute(struct newton_fit *fit, bool prune)
-{
- bool has_min_samples = true;
- struct queue_iterator it;
- struct newton_fit_orientation *_it;
-
- /* Not full, not ready to compute. */
- if (!queue_is_full(fit->orientations))
- return false;
-
- /* Inspect all the orientations. */
- for (queue_begin(fit->orientations, &it); it.ptr != NULL;
- queue_next(fit->orientations, &it)) {
- _it = (struct newton_fit_orientation *)it.ptr;
- /* If an orientation has too few samples, flag that. */
- CPRINTS(" orientation %u/%u", _it->nsamples,
- fit->min_orientation_samples);
- if (_it->nsamples < fit->min_orientation_samples) {
- has_min_samples = false;
- break;
- }
- }
-
- /* If all orientations have the minimum samples, we're done and can
- * compute the bias.
- */
- if (has_min_samples)
- return true;
-
- /* If we got here and prune is true, then we need to remove the oldest
- * entry to make room for new orientations.
- */
- if (prune)
- queue_advance_head(fit->orientations, 1);
-
- return false;
-}
-
-void newton_fit_reset(struct newton_fit *fit)
-{
- queue_init(fit->orientations);
-}
-
-bool newton_fit_accumulate(struct newton_fit *fit, fp_t x, fp_t y, fp_t z)
-{
- struct queue_iterator it;
- struct newton_fit_orientation *_it;
- fpv3_t v, delta;
-
- fpv3_init(v, x, y, z);
-
- /* Check if we can merge this new data point with an existing
- * orientation.
- */
- for (queue_begin(fit->orientations, &it); it.ptr != NULL;
- queue_next(fit->orientations, &it)) {
- _it = (struct newton_fit_orientation *)it.ptr;
-
- fpv3_sub(delta, v, _it->orientation);
- /* Skip entries that are too far away. */
- if (fpv3_dot(delta, delta) >= fit->nearness_threshold)
- continue;
-
- /* Merge new data point with this orientation. */
- fpv3_scalar_mul(_it->orientation,
- FLOAT_TO_FP(1.0f) - fit->new_pt_weight);
- fpv3_scalar_mul(v, fit->new_pt_weight);
- fpv3_add(_it->orientation, _it->orientation, v);
- if (_it->nsamples < 0xff)
- _it->nsamples++;
- return is_ready_to_compute(fit, false);
- }
-
- /* If queue isn't full. */
- if (!queue_is_full(fit->orientations)) {
- struct newton_fit_orientation entry;
-
- entry.nsamples = 1;
- fpv3_init(entry.orientation, x, y, z);
- queue_add_unit(fit->orientations, &entry);
-
- return is_ready_to_compute(fit, false);
- }
-
- return is_ready_to_compute(fit, true);
-}
-
-void newton_fit_compute(struct newton_fit *fit, fpv3_t bias, fp_t *radius)
-{
- struct queue_iterator it;
- struct newton_fit_orientation *_it;
- fpv3_t new_bias, offset, delta;
- fp_t error, new_error;
- uint32_t iteration = 0;
- fp_t inv_orient_count;
-
- if (queue_is_empty(fit->orientations))
- return;
-
- inv_orient_count = fp_div(FLOAT_TO_FP(1.0f),
- queue_count(fit->orientations));
-
- memcpy(new_bias, bias, sizeof(fpv3_t));
- new_error = compute_error(fit, new_bias);
-
- do {
- memcpy(bias, new_bias, sizeof(fpv3_t));
- error = new_error;
- fpv3_zero(offset);
-
- for (queue_begin(fit->orientations, &it); it.ptr != NULL;
- queue_next(fit->orientations, &it)) {
- fp_t mag;
-
- _it = (struct newton_fit_orientation *)it.ptr;
-
- fpv3_sub(delta, _it->orientation, bias);
- mag = fpv3_norm(delta);
- fpv3_scalar_mul(delta,
- fp_div(mag - FLOAT_TO_FP(1.0f), mag));
- fpv3_add(offset, offset, delta);
- }
-
- fpv3_scalar_mul(offset, inv_orient_count);
- fpv3_add(new_bias, bias, offset);
- new_error = compute_error(fit, new_bias);
- if (new_error > error)
- memcpy(new_bias, bias, sizeof(fpv3_t));
- ++iteration;
- } while (iteration < fit->max_iterations && new_error < error &&
- new_error > fit->error_threshold);
-
- memcpy(bias, new_bias, sizeof(fpv3_t));
-
- if (radius) {
- *radius = FLOAT_TO_FP(0.0f);
- for (queue_begin(fit->orientations, &it); it.ptr != NULL;
- queue_next(fit->orientations, &it)) {
- _it = (struct newton_fit_orientation *)it.ptr;
- fpv3_sub(delta, _it->orientation, bias);
- *radius += fpv3_norm(delta);
- }
- *radius *= inv_orient_count;
- }
-}
diff --git a/common/ocpc.c b/common/ocpc.c
deleted file mode 100644
index 3bc2a265d3..0000000000
--- a/common/ocpc.c
+++ /dev/null
@@ -1,767 +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.
- */
-
-/* OCPC - One Charger IC Per Type-C module */
-
-#include "battery.h"
-#include "battery_fuel_gauge.h"
-#include "charge_manager.h"
-#include "charge_state_v2.h"
-#include "charger.h"
-#include "common.h"
-#include "console.h"
-#include "hooks.h"
-#include "math_util.h"
-#include "ocpc.h"
-#include "timer.h"
-#include "usb_pd.h"
-#include "util.h"
-
-/*
- * These constants were chosen by tuning the PID loop to reduce oscillations and
- * minimize overshoot.
- */
-#define KP 1
-#define KP_DIV 4
-#define KI 1
-#define KI_DIV 15
-#define KD 1
-#define KD_DIV 10
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_CHARGER, outstr)
-#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args)
-#define CPRINT_VIZ(format, args...) \
-do { \
- if (viz_output) \
- cprintf(CC_CHARGER, format, ## args); \
-} while (0)
-#define CPRINTS_DBG(format, args...) \
-do { \
- if (debug_output) \
- cprints(CC_CHARGER, format, ## args); \
-} while (0)
-#define CPRINTF_DBG(format, args...) \
-do { \
- if (debug_output) \
- cprintf(CC_CHARGER, format, ## args); \
-} while (0)
-
-
-/* Code refactor will be needed if more than 2 charger chips are present */
-BUILD_ASSERT(CHARGER_NUM == 2);
-
-static int k_p = KP;
-static int k_i = KI;
-static int k_d = KD;
-static int k_p_div = KP_DIV;
-static int k_i_div = KI_DIV;
-static int k_d_div = KD_DIV;
-static int debug_output;
-static int viz_output;
-
-#define NUM_RESISTANCE_SAMPLES 8
-#define COMBINED_IDX 0
-#define RBATT_IDX 1
-#define RSYS_IDX 2
-static int resistance_tbl[NUM_RESISTANCE_SAMPLES][3] = {
- /* Rsys+Rbatt Rbatt Rsys */
- {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0},
- {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0},
- {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0},
- {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0},
- {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0},
- {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0},
- {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0},
- {CONFIG_OCPC_DEF_RBATT_MOHMS, CONFIG_OCPC_DEF_RBATT_MOHMS, 0},
-};
-static int resistance_tbl_idx;
-static int mean_resistance[3];
-static int stddev_resistance[3];
-static int ub[3];
-static int lb[3];
-
-enum phase {
- PHASE_UNKNOWN = -1,
- PHASE_PRECHARGE,
- PHASE_CC,
- PHASE_CV_TRIP,
- PHASE_CV_COMPLETE,
-};
-
-__overridable void board_ocpc_init(struct ocpc_data *ocpc)
-{
-}
-
-static enum ec_error_list ocpc_precharge_enable(bool enable);
-
-static void calc_resistance_stats(struct ocpc_data *ocpc)
-{
- int i;
- int j;
- int sum;
- int cols = 3;
- int act_chg = ocpc->active_chg_chip;
-
- /* Only perform separate stats on Rsys and Rbatt if necessary. */
- if ((ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP))
- cols = 1;
-
- /* Calculate mean */
- for (i = 0; i < cols; i++) {
- sum = 0;
- for (j = 0; j < NUM_RESISTANCE_SAMPLES; j++) {
- sum += resistance_tbl[j][i];
- CPRINTF_DBG("%d ", resistance_tbl[j][i]);
- }
- CPRINTF_DBG("\n");
-
- mean_resistance[i] = sum / NUM_RESISTANCE_SAMPLES;
-
- /* Calculate standard deviation */
- sum = 0;
- for (j = 0; j < NUM_RESISTANCE_SAMPLES; j++)
- sum += POW2(resistance_tbl[j][i] - mean_resistance[i]);
-
- stddev_resistance[i] = fp_sqrtf(INT_TO_FP(sum /
- NUM_RESISTANCE_SAMPLES));
- stddev_resistance[i] = FP_TO_INT(stddev_resistance[i]);
- /*
- * Don't let our stddev collapse to 0 to continually consider
- * new values.
- */
- stddev_resistance[i] = MAX(stddev_resistance[i], 1);
- CPRINTS_DBG("%d: mean: %d stddev: %d", i, mean_resistance[i],
- stddev_resistance[i]);
- lb[i] = MAX(0, mean_resistance[i] - (3 * stddev_resistance[i]));
- ub[i] = mean_resistance[i] + (3 * stddev_resistance[i]);
- }
-}
-
-static bool is_within_range(struct ocpc_data *ocpc, int combined, int rbatt,
- int rsys)
-{
- int act_chg = ocpc->active_chg_chip;
- bool valid;
-
- /* Discard measurements not within a 6 std. dev. window. */
- if ((ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP)) {
- /* We only know the combined Rsys+Rbatt */
- valid = (combined > 0) &&
- (combined <= ub[COMBINED_IDX]) &&
- (combined >= lb[COMBINED_IDX]);
- } else {
- valid = (rsys <= ub[RSYS_IDX]) && (rsys >= lb[RSYS_IDX]) &&
- (rbatt <= ub[RBATT_IDX]) && (rbatt >= lb[RBATT_IDX]) &&
- (rsys > 0) && (rbatt > 0);
- }
-
- if (!valid)
- CPRINTS_DBG("Discard Rc:%d Rb:%d Rs:%d", combined, rbatt, rsys);
-
- return valid;
-}
-
-enum ec_error_list ocpc_calc_resistances(struct ocpc_data *ocpc,
- struct batt_params *battery)
-{
- int act_chg = ocpc->active_chg_chip;
- static bool seeded;
- static int initial_samples;
- int combined;
- int rsys = -1;
- int rbatt = -1;
-
- /*
- * In order to actually calculate the resistance, we need to make sure
- * we're actually charging the battery at a significant rate. The LSB
- * of a charger IC can be as high as 96mV. Assuming a resistance of 60
- * mOhms, we would need a current of 1666mA to have a voltage delta of
- * 100mV.
- */
- if ((battery->current <= 1666) ||
- (!(ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP) &&
- (ocpc->isys_ma <= 0)) ||
- (ocpc->vsys_aux_mv < ocpc->vsys_mv)) {
- CPRINTS_DBG("Not charging... won't determine resistance");
- CPRINTS_DBG("vsys_aux_mv: %dmV vsys_mv: %dmV",
- ocpc->vsys_aux_mv, ocpc->vsys_mv);
- return EC_ERROR_INVALID_CONFIG; /* We must be charging */
- }
-
- /*
- * The combined system and battery resistance is the delta between Vsys
- * and Vbatt divided by Ibatt.
- */
- if ((ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP)) {
- /*
- * There's no provision to measure Isys, so we cannot separate
- * out Rsys from Rbatt.
- */
- combined = ((ocpc->vsys_aux_mv - battery->voltage) * 1000) /
- battery->current;
- } else {
- rsys = ((ocpc->vsys_aux_mv - ocpc->vsys_mv) * 1000) /
- ocpc->isys_ma;
- rbatt = ((ocpc->vsys_mv - battery->voltage) * 1000) /
- battery->current;
- combined = rsys + rbatt;
- }
-
- /* Discard measurements not within a 6 std dev window. */
- if ((!seeded) ||
- (seeded && is_within_range(ocpc, combined, rbatt, rsys))) {
- if (!(ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP)) {
- resistance_tbl[resistance_tbl_idx][RSYS_IDX] =
- MAX(rsys, 0);
- resistance_tbl[resistance_tbl_idx][RBATT_IDX] =
- MAX(rbatt, CONFIG_OCPC_DEF_RBATT_MOHMS);
- }
- resistance_tbl[resistance_tbl_idx][COMBINED_IDX] =
- MAX(combined, CONFIG_OCPC_DEF_RBATT_MOHMS);
- calc_resistance_stats(ocpc);
- resistance_tbl_idx = (resistance_tbl_idx + 1) %
- NUM_RESISTANCE_SAMPLES;
- }
-
- if (seeded) {
- ocpc->combined_rsys_rbatt_mo =
- MAX(mean_resistance[COMBINED_IDX],
- CONFIG_OCPC_DEF_RBATT_MOHMS);
-
- if (!(ocpc->chg_flags[act_chg] & OCPC_NO_ISYS_MEAS_CAP)) {
- ocpc->rsys_mo = mean_resistance[RSYS_IDX];
- ocpc->rbatt_mo = MAX(mean_resistance[RBATT_IDX],
- CONFIG_OCPC_DEF_RBATT_MOHMS);
- CPRINTS_DBG("Rsys: %dmOhm Rbatt: %dmOhm",
- ocpc->rsys_mo, ocpc->rbatt_mo);
- }
-
- CPRINTS_DBG("Rsys+Rbatt: %dmOhm", ocpc->combined_rsys_rbatt_mo);
- } else {
- seeded = ++initial_samples >= (2 * NUM_RESISTANCE_SAMPLES) ?
- true : false;
- }
-
- return EC_SUCCESS;
-}
-
-int ocpc_config_secondary_charger(int *desired_input_current,
- struct ocpc_data *ocpc,
- int voltage_mv, int current_ma)
-{
- int rv = EC_SUCCESS;
- struct batt_params batt;
- const struct battery_info *batt_info;
- struct charger_params charger;
- int vsys_target = 0;
- int drive = 0;
- int i_ma = 0;
- static int i_ma_CC_CV;
- int min_vsys_target;
- int error = 0;
- int derivative = 0;
- static enum phase ph;
- static int prev_limited;
- int chgnum;
- enum ec_error_list result;
- static int iterations;
- int i_step;
- static timestamp_t delay;
- int i, step, loc;
- bool icl_reached = false;
- static timestamp_t precharge_exit;
-
- /*
- * There's nothing to do if we're not using this charger. Should
- * there be more than two charger ICs in the future, the following check
- * should change to ensure that only the active charger IC is acted
- * upon.
- */
- chgnum = charge_get_active_chg_chip();
- if (chgnum != CHARGER_SECONDARY)
- return EC_ERROR_INVAL;
-
- batt_info = battery_get_info();
-
- if (current_ma == 0) {
- vsys_target = voltage_mv;
- goto set_vsys;
- }
-
- /*
- * Check to see if the charge FET is disabled. If it's disabled, the
- * charging loop is broken and increasing VSYS will not actually help.
- * Therefore, don't make any changes at this time.
- */
- if (battery_is_charge_fet_disabled() &&
- (battery_get_disconnect_state() == BATTERY_NOT_DISCONNECTED)) {
- CPRINTS("CFET disabled; not changing VSYS!");
-
- /*
- * Let's check back in 5 seconds to see if the CFET is enabled
- * now. Note that if this continues to occur, we'll keep
- * pushing this out.
- */
- delay = get_time();
- delay.val += (5 * SECOND);
- return EC_ERROR_INVALID_CONFIG;
- }
-
- /*
- * The CFET status changed recently, wait until it's no longer disabled
- * for awhile before modifying VSYS. This could be the fuel gauge
- * performing some impedence calculations.
- */
- if (!timestamp_expired(delay, NULL))
- return EC_ERROR_BUSY;
-
- result = charger_set_vsys_compensation(chgnum, ocpc, current_ma,
- voltage_mv);
- switch (result) {
- case EC_SUCCESS:
- /* No further action required, so we're done here. */
- return EC_SUCCESS;
-
- case EC_ERROR_UNIMPLEMENTED:
- /* Let's get to work */
- break;
-
- default:
- /* Something went wrong configuring the auxiliary charger IC. */
- CPRINTS("Failed to set VSYS compensation! (%d) (result: %d)",
- chgnum, result);
- return result;
- }
-
- if (ocpc->last_vsys == OCPC_UNINIT) {
- ph = PHASE_UNKNOWN;
- precharge_exit.val = 0;
- iterations = 0;
- }
-
-
- /*
- * We need to induce a current flow that matches the requested current
- * by raising VSYS. Let's start by getting the latest data that we
- * know of.
- */
- batt_info = battery_get_info();
- battery_get_params(&batt);
- ocpc_get_adcs(ocpc);
- charger_get_params(&charger);
-
-
- /*
- * If the system is in S5/G3, we can calculate the board and battery
- * resistances.
- */
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF |
- CHIPSET_STATE_ANY_SUSPEND)) {
- /*
- * In the first few iterations of the loop, charging isn't
- * stable/correct so making the calculation then leads to some
- * strange values throwing off the loop even more. However,
- * after those initial iterations it then begins to behave as
- * expected. From there onwards, the resistance values aren't
- * changing _too_ rapidly. This is why we calculate with every
- * modulo 4 interval.
- */
- iterations++;
- if (!(iterations % 4))
- ocpc_calc_resistances(ocpc, &batt);
- iterations %= 5;
- }
-
- /* Set our current target accordingly. */
- if (batt.desired_voltage) {
- if (((batt.voltage < batt_info->voltage_min) ||
- ((batt.voltage < batt_info->voltage_normal) &&
- (current_ma <= batt_info->precharge_current))) &&
- (ph != PHASE_PRECHARGE)) {
- /*
- * If the charger IC doesn't support the linear charge
- * feature, proceed to the CC phase.
- */
- result = ocpc_precharge_enable(true);
- if (result == EC_ERROR_UNIMPLEMENTED) {
- ph = PHASE_CC;
- } else if (result == EC_SUCCESS) {
- CPRINTS("OCPC: Enabling linear precharge");
- ph = PHASE_PRECHARGE;
- i_ma = current_ma;
- }
- } else if (batt.voltage < batt.desired_voltage) {
- if ((ph == PHASE_PRECHARGE) &&
- (current_ma >
- batt_info->precharge_current)) {
- /*
- * Precharge phase is complete. Now set the
- * target VSYS to the battery voltage to prevent
- * a large current spike during the transition.
- */
- /*
- * If we'd like to exit precharge, let's wait a
- * short delay.
- */
- if (!precharge_exit.val) {
- CPRINTS("OCPC: Preparing to exit "
- "precharge");
- precharge_exit = get_time();
- precharge_exit.val += 3 * SECOND;
- }
- if (timestamp_expired(precharge_exit, NULL)) {
- CPRINTS("OCPC: Precharge complete");
- charger_set_voltage(CHARGER_SECONDARY,
- batt.voltage);
- ocpc->last_vsys = batt.voltage;
- ocpc_precharge_enable(false);
- ph = PHASE_CC;
- precharge_exit.val = 0;
- }
- }
-
- if ((ph != PHASE_PRECHARGE) && (ph < PHASE_CV_TRIP))
- ph = PHASE_CC;
- i_ma = current_ma;
- } else {
- /*
- * Once the battery voltage reaches the desired voltage,
- * we should note that we've reached the CV step and set
- * VSYS to the desired CV + offset.
- */
- i_ma = batt.current;
- ph = ph == PHASE_CC ? PHASE_CV_TRIP : PHASE_CV_COMPLETE;
- if (ph == PHASE_CV_TRIP)
- i_ma_CC_CV = batt.current;
-
- }
- }
-
- /* Ensure our target is not negative. */
- i_ma = MAX(i_ma, 0);
-
- /* Convert desired mA to what the charger could actually regulate to. */
- i_step = (int)charger_get_info()->current_step;
- i_ma = (i_ma / i_step) * i_step;
-
- /*
- * We'll use our current target and our combined Rsys+Rbatt to seed our
- * VSYS target. However, we'll use a PID loop to correct the error and
- * help drive VSYS to what it _should_ be in order to reach our current
- * target. The first time through this function, we won't make any
- * corrections in order to determine our initial error.
- */
- if (ocpc->last_vsys != OCPC_UNINIT) {
- error = i_ma - batt.current;
- /* Add some hysteresis. */
- if (ABS(error) < (i_step / 2))
- error = 0;
-
- /* Make a note if we're significantly over target. */
- if (error < -100)
- CPRINTS("OCPC: over target %dmA", error * -1);
-
- derivative = error - ocpc->last_error;
- ocpc->last_error = error;
- ocpc->integral += error;
- if (ocpc->integral > 500)
- ocpc->integral = 500;
- }
-
- CPRINTS_DBG("phase = %d", ph);
- CPRINTS_DBG("error = %dmA", error);
- CPRINTS_DBG("derivative = %d", derivative);
- CPRINTS_DBG("integral = %d", ocpc->integral);
- CPRINTS_DBG("batt.voltage = %dmV", batt.voltage);
- CPRINTS_DBG("batt.desired_voltage = %dmV", batt.desired_voltage);
- CPRINTS_DBG("batt.desired_current = %dmA", batt.desired_current);
- CPRINTS_DBG("batt.current = %dmA", batt.current);
- CPRINTS_DBG("i_ma = %dmA", i_ma);
-
- min_vsys_target = MIN(batt.voltage, batt.desired_voltage);
- CPRINTS_DBG("min_vsys_target = %d", min_vsys_target);
-
- /* Obtain the drive from our PID controller. */
- if ((ocpc->last_vsys != OCPC_UNINIT) &&
- (ph > PHASE_PRECHARGE)) {
- drive = (k_p * error / k_p_div) +
- (k_i * ocpc->integral / k_i_div) +
- (k_d * derivative / k_d_div);
- /*
- * Let's limit upward transitions to 10mV. It's okay to reduce
- * VSYS rather quickly, but we'll be conservative on
- * increasing VSYS.
- */
- if (drive > 10)
- drive = 10;
- CPRINTS_DBG("drive = %d", drive);
- }
-
- /*
- * For the pre-charge phase, simply keep the VSYS target at the desired
- * voltage.
- */
- if (ph == PHASE_PRECHARGE)
- vsys_target = batt.desired_voltage;
-
- /*
- * Adjust our VSYS target by applying the calculated drive. Note that
- * we won't apply our drive the first time through this function such
- * that we can determine our initial error.
- */
- if ((ocpc->last_vsys != OCPC_UNINIT) && (ph > PHASE_PRECHARGE))
- vsys_target = ocpc->last_vsys + drive;
-
- /*
- * Once we're in the CV region, all we need to do is keep VSYS at the
- * desired voltage.
- */
- if (ph == PHASE_CV_TRIP) {
- vsys_target = batt.desired_voltage +
- ((i_ma_CC_CV *
- ocpc->combined_rsys_rbatt_mo) / 1000);
- CPRINTS_DBG("i_ma_CC_CV = %d", i_ma_CC_CV);
- }
- if (ph == PHASE_CV_COMPLETE)
- vsys_target = batt.desired_voltage +
- ((batt_info->precharge_current *
- ocpc->combined_rsys_rbatt_mo) / 1000);
-
- /*
- * Ensure VSYS is no higher than the specified maximum battery voltage
- * plus the voltage drop across the system.
- */
- vsys_target = CLAMP(vsys_target, min_vsys_target,
- batt_info->voltage_max +
- (i_ma * ocpc->combined_rsys_rbatt_mo / 1000));
-
- /* If we're input current limited, we cannot increase VSYS any more. */
- CPRINTS_DBG("OCPC: Inst. Input Current: %dmA (Limit: %dmA)",
- ocpc->secondary_ibus_ma, *desired_input_current);
-
- if (charger_is_icl_reached(chgnum, &icl_reached) != EC_SUCCESS) {
- /*
- * If the charger doesn't support telling us, assume that the
- * input current limit is reached if we're consuming more than
- * 95% of the limit.
- */
- if (ocpc->secondary_ibus_ma >=
- (*desired_input_current * 95 / 100))
- icl_reached = true;
- }
-
- if (icl_reached && (vsys_target > ocpc->last_vsys) &&
- (ocpc->last_vsys != OCPC_UNINIT)) {
- if (!prev_limited)
- CPRINTS("Input limited! Not increasing VSYS");
- prev_limited = 1;
- return rv;
- }
- prev_limited = 0;
-
-set_vsys:
- /* VSYS should never be below the battery's min voltage. */
- vsys_target = MAX(vsys_target, batt_info->voltage_min);
- /* To reduce spam, only print when we change VSYS significantly. */
- if ((ABS(vsys_target - ocpc->last_vsys) > 10) || debug_output)
- CPRINTS("OCPC: Target VSYS: %dmV", vsys_target);
- charger_set_voltage(CHARGER_SECONDARY, vsys_target);
- ocpc->last_vsys = vsys_target;
-
- /*
- * Print a visualization graph of the actual current vs. the target.
- * Each position represents 5% of the target current.
- */
- if (i_ma != 0) {
- step = 5 * i_ma / 100;
- loc = error / step;
- loc = CLAMP(loc, -10, 10);
- CPRINT_VIZ("[");
- for (i = -10; i <= 10; i++) {
- if (i == 0)
- CPRINT_VIZ(loc == 0 ? "#" : "|");
- else
- CPRINT_VIZ(i == loc ? "o" : "-");
- }
- CPRINT_VIZ("] (actual)%dmA (desired)%dmA\n", batt.current,
- i_ma);
- }
-
- return rv;
-}
-
-void ocpc_get_adcs(struct ocpc_data *ocpc)
-{
- int val;
-
- val = 0;
- if (!charger_get_vbus_voltage(CHARGER_PRIMARY, &val))
- ocpc->primary_vbus_mv = val;
-
- val = 0;
- if (!charger_get_input_current(CHARGER_PRIMARY, &val))
- ocpc->primary_ibus_ma = val;
-
- val = 0;
- if (!charger_get_actual_voltage(CHARGER_PRIMARY, &val))
- ocpc->vsys_mv = val;
-
- if (board_get_charger_chip_count() <= CHARGER_SECONDARY) {
- ocpc->secondary_vbus_mv = 0;
- ocpc->secondary_ibus_ma = 0;
- ocpc->vsys_aux_mv = 0;
- ocpc->isys_ma = 0;
- return;
- }
-
- val = 0;
- if (!charger_get_vbus_voltage(CHARGER_SECONDARY, &val))
- ocpc->secondary_vbus_mv = val;
-
- val = 0;
- if (!charger_get_input_current(CHARGER_SECONDARY, &val))
- ocpc->secondary_ibus_ma = val;
-
- val = 0;
- if (!charger_get_actual_voltage(CHARGER_SECONDARY, &val))
- ocpc->vsys_aux_mv = val;
-
- val = 0;
- if (!charger_get_actual_current(CHARGER_SECONDARY, &val))
- ocpc->isys_ma = val;
-}
-
-__overridable void ocpc_get_pid_constants(int *kp, int *kp_div,
- int *ki, int *ki_div,
- int *kd, int *kd_div)
-{
-}
-
-static enum ec_error_list ocpc_precharge_enable(bool enable)
-{
- /* Enable linear charging on the primary charger IC. */
- int rv = charger_enable_linear_charge(CHARGER_PRIMARY, enable);
-
- if (rv)
- CPRINTS("OCPC: Failed to %sble linear charge!", enable ? "ena"
- : "dis");
-
- return rv;
-}
-
-void ocpc_reset(struct ocpc_data *ocpc)
-{
- struct batt_params batt;
-
- battery_get_params(&batt);
- ocpc->integral = 0;
- ocpc->last_error = 0;
- ocpc->last_vsys = OCPC_UNINIT;
-
- /*
- * Initialize the VSYS target on the aux chargers to the current battery
- * voltage to avoid a large spike.
- */
- if (ocpc->active_chg_chip > CHARGER_PRIMARY && batt.voltage > 0) {
- CPRINTS("OCPC: C%d Init VSYS to %dmV", ocpc->active_chg_chip,
- batt.voltage);
- charger_set_voltage(ocpc->active_chg_chip, batt.voltage);
- }
-
- /*
- * See(b:191347747) When linear precharge is enabled, it may affect
- * the charging behavior from the primary charger IC. Therefore as
- * a part of the reset process, we need to disable linear precharge.
- */
- ocpc_precharge_enable(false);
-}
-
-static void ocpc_set_pid_constants(void)
-{
- ocpc_get_pid_constants(&k_p, &k_p_div, &k_i, &k_i_div, &k_d, &k_d_div);
-}
-DECLARE_HOOK(HOOK_INIT, ocpc_set_pid_constants, HOOK_PRIO_DEFAULT);
-
-void ocpc_init(struct ocpc_data *ocpc)
-{
- /*
- * We can start off assuming that the board resistance is 0 ohms
- * and later on, we can update this value if we charge the
- * system in suspend or off.
- */
- ocpc->combined_rsys_rbatt_mo = CONFIG_OCPC_DEF_RBATT_MOHMS;
- ocpc->rbatt_mo = CONFIG_OCPC_DEF_RBATT_MOHMS;
-
- board_ocpc_init(ocpc);
-}
-
-static int command_ocpcdebug(int argc, char **argv)
-{
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- if (!strncmp(argv[1], "ena", 3)) {
- debug_output = true;
- viz_output = false;
- } else if (!strncmp(argv[1], "dis", 3)) {
- debug_output = false;
- viz_output = false;
- } else if (!strncmp(argv[1], "viz", 3)) {
- debug_output = false;
- viz_output = true;
- } else if (!strncmp(argv[1], "all", 3)) {
- debug_output = true;
- viz_output = true;
- } else {
- return EC_ERROR_PARAM1;
- }
-
- return EC_SUCCESS;
-}
-DECLARE_SAFE_CONSOLE_COMMAND(ocpcdebug, command_ocpcdebug,
- "<enable/viz/all/disable",
- "Enable/disable debug prints for OCPC data. "
- "Enable turns on text debug, viz shows a graph."
- "Each segment is 5% of current target. All shows"
- " both. Disable shows no debug output.");
-
-static int command_ocpcpid(int argc, char **argv)
-{
- int *num, *denom;
-
- if (argc == 4) {
- switch (argv[1][0]) {
- case 'p':
- num = &k_p;
- denom = &k_p_div;
- break;
-
- case 'i':
- num = &k_i;
- denom = &k_i_div;
- break;
-
- case 'd':
- num = &k_d;
- denom = &k_d_div;
- break;
- default:
- return EC_ERROR_PARAM1;
- }
-
- *num = atoi(argv[2]);
- *denom = atoi(argv[3]);
- }
-
- /* Print the current constants */
- ccprintf("Kp = %d / %d\n", k_p, k_p_div);
- ccprintf("Ki = %d / %d\n", k_i, k_i_div);
- ccprintf("Kd = %d / %d\n", k_d, k_d_div);
- return EC_SUCCESS;
-}
-DECLARE_SAFE_CONSOLE_COMMAND(ocpcpid, command_ocpcpid,
- "[<k/p/d> <numerator> <denominator>]",
- "Show/Set PID constants for OCPC PID loop");
diff --git a/common/onewire.c b/common/onewire.c
deleted file mode 100644
index cdb5837255..0000000000
--- a/common/onewire.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/* Copyright 2012 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.
- */
-
-/* 1-wire interface module for Chrome EC */
-
-#include "common.h"
-#include "gpio.h"
-#include "task.h"
-#include "timer.h"
-
-/*
- * Standard speed; all timings padded by 2 usec for safety.
- *
- * Note that these timing are actually _longer_ than legacy 1-wire standard
- * speed because we're running the 1-wire bus at 3.3V instead of 5V.
- */
-#define T_RSTL 602 /* Reset low pulse; 600-960 us */
-#define T_MSP 72 /* Presence detect sample time; 70-75 us */
-#define T_RSTH (68 + 260 + 5 + 2) /* Reset high; tPDHmax + tPDLmax + tRECmin */
-#define T_SLOT 70 /* Timeslot; >67 us */
-#define T_W0L 63 /* Write 0 low; 62-120 us */
-#define T_W1L 7 /* Write 1 low; 5-15 us */
-#define T_RL 7 /* Read low; 5-15 us */
-#define T_MSR 9 /* Read sample time; <15 us. Must be at least 200 ns after
- * T_RL since that's how long the signal takes to be pulled
- * up on our board. */
-
-/**
- * Output low on the bus for <usec> us, then switch back to open-drain input.
- */
-static void output0(int usec)
-{
- gpio_set_flags(GPIO_ONEWIRE,
- GPIO_OPEN_DRAIN | GPIO_OUTPUT | GPIO_OUT_LOW);
- udelay(usec);
- gpio_set_flags(GPIO_ONEWIRE, GPIO_INPUT);
-}
-
-/**
- * Read a bit.
- */
-static int readbit(void)
-{
- int bit;
-
- /*
- * The delay between sending the output pulse and reading the bit is
- * extremely timing sensitive, so disable interrupts.
- */
- interrupt_disable();
-
- /* Output low */
- output0(T_RL);
-
- /*
- * Delay to let peripheral release the line if it wants to send
- * a 1-bit
- */
- udelay(T_MSR - T_RL);
-
- /* Read bit */
- bit = gpio_get_level(GPIO_ONEWIRE);
-
- /*
- * Enable interrupt as soon as we've read the bit. The delay to the
- * end of the timeslot is a lower bound, so additional latency here is
- * harmless.
- */
- interrupt_enable();
-
- /* Delay to end of timeslot */
- udelay(T_SLOT - T_MSR);
- return bit;
-}
-
-/**
- * Write a bit.
- */
-static void writebit(int bit)
-{
- /*
- * The delays in the output-low signal for sending 0 and 1 bits are
- * extremely timing sensitive, so disable interrupts during that time.
- * Interrupts can be enabled again as soon as the output is switched
- * back to open-drain, since the delay for the rest of the timeslot is
- * a lower bound.
- */
- if (bit) {
- interrupt_disable();
- output0(T_W1L);
- interrupt_enable();
- udelay(T_SLOT - T_W1L);
- } else {
- interrupt_disable();
- output0(T_W0L);
- interrupt_enable();
- udelay(T_SLOT - T_W0L);
- }
-
-}
-
-int onewire_reset(void)
-{
- /* Start transaction with controller reset pulse */
- output0(T_RSTL);
-
- /* Wait for presence detect sample time.
- *
- * (Alternately, we could poll waiting for a 1-bit indicating our pulse
- * has let go, then poll up to max time waiting for a 0-bit indicating
- * the peripheral has responded.)
- */
- udelay(T_MSP);
-
- if (gpio_get_level(GPIO_ONEWIRE))
- return EC_ERROR_UNKNOWN;
-
- /*
- * Wait for end of presence pulse.
- *
- * (Alternately, we could poll waiting for a 1-bit.)
- */
- udelay(T_RSTH - T_MSP);
-
- return EC_SUCCESS;
-}
-
-int onewire_read(void)
-{
- int data = 0;
- int i;
-
- for (i = 0; i < 8; i++)
- data |= readbit() << i; /* LSB first */
-
- return data;
-}
-
-void onewire_write(int data)
-{
- int i;
-
- for (i = 0; i < 8; i++)
- writebit((data >> i) & 0x01); /* LSB first */
-}
diff --git a/common/online_calibration.c b/common/online_calibration.c
deleted file mode 100644
index 3bc56f85c7..0000000000
--- a/common/online_calibration.c
+++ /dev/null
@@ -1,394 +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.
- */
-
-#include "accelgyro.h"
-#include "atomic.h"
-#include "hwtimer.h"
-#include "online_calibration.h"
-#include "common.h"
-#include "mag_cal.h"
-#include "util.h"
-#include "vec3.h"
-#include "task.h"
-#include "ec_commands.h"
-#include "accel_cal.h"
-#include "mkbp_event.h"
-#include "gyro_cal.h"
-
-#define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ##args)
-
-#ifndef CONFIG_MKBP_EVENT
-#error "Must use CONFIG_MKBP_EVENT for online calibration"
-#endif /* CONFIG_MKBP_EVENT */
-
-/** Bitmap telling which online calibration values are valid. */
-static uint32_t sensor_calib_cache_valid_map;
-/** Bitmap telling which online calibration values are dirty. */
-static uint32_t sensor_calib_cache_dirty_map;
-
-struct mutex g_calib_cache_mutex;
-
-static int get_temperature(struct motion_sensor_t *sensor, int *temp)
-{
- struct online_calib_data *entry = sensor->online_calib_data;
- uint32_t now;
-
- if (sensor->drv->read_temp == NULL)
- return EC_ERROR_UNIMPLEMENTED;
-
- now = __hw_clock_source_read();
- if (entry->last_temperature < 0 ||
- time_until(entry->last_temperature_timestamp, now) >
- CONFIG_TEMP_CACHE_STALE_THRES) {
- int t;
- int rc = sensor->drv->read_temp(sensor, &t);
-
- if (rc == EC_SUCCESS) {
- entry->last_temperature = t;
- entry->last_temperature_timestamp = now;
- } else {
- return rc;
- }
- }
-
- *temp = entry->last_temperature;
- return EC_SUCCESS;
-}
-
-static void data_int16_to_fp(const struct motion_sensor_t *s,
- const int16_t *data, fpv3_t out)
-{
- int i;
- fp_t range = INT_TO_FP(s->current_range);
-
- for (i = 0; i < 3; ++i) {
- fp_t v = INT_TO_FP((int32_t)data[i]);
-
- out[i] = fp_div(v, INT_TO_FP((data[i] >= 0) ? 0x7fff : 0x8000));
- out[i] = fp_mul(out[i], range);
- /* Check for overflow */
- out[i] = CLAMP(out[i], -range, range);
- }
-}
-
-static void data_fp_to_int16(const struct motion_sensor_t *s, const fpv3_t data,
- int16_t *out)
-{
- int i;
- fp_t range = INT_TO_FP(s->current_range);
-
- for (i = 0; i < 3; ++i) {
- int32_t iv;
- fp_t v = fp_div(data[i], range);
-
- v = fp_mul(v, INT_TO_FP(0x7fff));
- iv = FP_TO_INT(v);
- /* Check for overflow */
- out[i] = ec_motion_sensor_clamp_i16(iv);
- }
-}
-
-/**
- * Check a gyroscope for new bias. This function checks a given sensor (must be
- * a gyroscope) for new bias values. If found, it will update the appropriate
- * caches and notify the AP.
- *
- * @param sensor Pointer to the gyroscope sensor to check.
- */
-static bool check_gyro_cal_new_bias(struct motion_sensor_t *sensor,
- fpv3_t bias_out)
-{
- struct online_calib_data *calib_data =
- (struct online_calib_data *)sensor->online_calib_data;
- struct gyro_cal_data *data =
- (struct gyro_cal_data *)calib_data->type_specific_data;
- int temp_out;
- uint32_t timestamp_out;
-
- /* Check that we have a new bias. */
- if (data == NULL || calib_data == NULL ||
- !gyro_cal_new_bias_available(&data->gyro_cal))
- return false;
-
- /* Read the calibration values. */
- gyro_cal_get_bias(&data->gyro_cal, bias_out, &temp_out, &timestamp_out);
- return true;
-}
-
-static void set_gyro_cal_cache_values(struct motion_sensor_t *sensor,
- fpv3_t bias)
-{
- size_t sensor_num = sensor - motion_sensors;
- struct online_calib_data *calib_data =
- (struct online_calib_data *)sensor->online_calib_data;
-
- mutex_lock(&g_calib_cache_mutex);
- /* Convert result to the right scale and save to cache. */
- data_fp_to_int16(sensor, bias, calib_data->cache);
- /* Set valid and dirty. */
- sensor_calib_cache_valid_map |= BIT(sensor_num);
- sensor_calib_cache_dirty_map |= BIT(sensor_num);
- mutex_unlock(&g_calib_cache_mutex);
- /* Notify the AP. */
- mkbp_send_event(EC_MKBP_EVENT_ONLINE_CALIBRATION);
-}
-
-/**
- * Update the data stream (accel/mag) for a given sensor and data in all
- * gyroscopes that are interested.
- *
- * @param sensor Pointer to the sensor that generated the data.
- * @param data 3 floats/fixed point data points generated by the sensor.
- * @param timestamp The timestamp at which the data was generated.
- */
-static void update_gyro_cal(struct motion_sensor_t *sensor, fpv3_t data,
- uint32_t timestamp)
-{
- int i;
- fpv3_t gyro_cal_data_out;
-
- /*
- * Find gyroscopes, while we don't currently have instance where more
- * than one are present in a board, this loop will work with any number
- * of them.
- */
- for (i = 0; i < SENSOR_COUNT; ++i) {
- struct motion_sensor_t *s = motion_sensors + i;
- struct gyro_cal_data *gyro_cal_data =
- (struct gyro_cal_data *)
- s->online_calib_data->type_specific_data;
- bool has_new_gyro_cal_bias = false;
-
- /*
- * If we're not looking at a gyroscope OR if the calibration
- * data is NULL, skip this sensor.
- */
- if (s->type != MOTIONSENSE_TYPE_GYRO || gyro_cal_data == NULL)
- continue;
-
- /*
- * Update the appropriate data stream (accel/mag) depending on
- * which sensors the gyroscope is tracking.
- */
- if (sensor->type == MOTIONSENSE_TYPE_ACCEL &&
- gyro_cal_data->accel_sensor_id == sensor - motion_sensors) {
- gyro_cal_update_accel(&gyro_cal_data->gyro_cal,
- timestamp, data[X], data[Y],
- data[Z]);
- has_new_gyro_cal_bias =
- check_gyro_cal_new_bias(s, gyro_cal_data_out);
- } else if (sensor->type == MOTIONSENSE_TYPE_MAG &&
- gyro_cal_data->mag_sensor_id ==
- sensor - motion_sensors) {
- gyro_cal_update_mag(&gyro_cal_data->gyro_cal, timestamp,
- data[X], data[Y], data[Z]);
- has_new_gyro_cal_bias =
- check_gyro_cal_new_bias(s, gyro_cal_data_out);
- }
-
- if (has_new_gyro_cal_bias)
- set_gyro_cal_cache_values(s, gyro_cal_data_out);
- }
-}
-
-void online_calibration_init(void)
-{
- size_t i;
-
- for (i = 0; i < SENSOR_COUNT; i++) {
- struct motion_sensor_t *s = motion_sensors + i;
- void *type_specific_data = NULL;
-
- if (s->online_calib_data) {
- s->online_calib_data->last_temperature = -1;
- type_specific_data =
- s->online_calib_data->type_specific_data;
- }
-
- if (!type_specific_data)
- continue;
-
- switch (s->type) {
- case MOTIONSENSE_TYPE_ACCEL: {
- accel_cal_reset((struct accel_cal *)type_specific_data);
- break;
- }
- case MOTIONSENSE_TYPE_MAG: {
- init_mag_cal((struct mag_cal_t *)type_specific_data);
- break;
- }
- case MOTIONSENSE_TYPE_GYRO: {
- init_gyro_cal(
- &((struct gyro_cal_data *)type_specific_data)
- ->gyro_cal);
- break;
- }
- default:
- break;
- }
- }
-}
-
-bool online_calibration_has_new_values(void)
-{
- bool has_dirty;
-
- mutex_lock(&g_calib_cache_mutex);
- has_dirty = sensor_calib_cache_dirty_map != 0;
- mutex_unlock(&g_calib_cache_mutex);
-
- return has_dirty;
-}
-
-bool online_calibration_read(struct motion_sensor_t *sensor,
- struct ec_response_online_calibration_data *out)
-{
- int sensor_num = sensor - motion_sensors;
- bool has_valid;
-
- mutex_lock(&g_calib_cache_mutex);
- has_valid = (sensor_calib_cache_valid_map & BIT(sensor_num)) != 0;
- if (has_valid) {
- /* Update data in out */
- memcpy(out->data, sensor->online_calib_data->cache,
- sizeof(out->data));
- /* Clear dirty bit */
- sensor_calib_cache_dirty_map &= ~(1 << sensor_num);
- }
- mutex_unlock(&g_calib_cache_mutex);
-
- return has_valid;
-}
-
-int online_calibration_process_data(struct ec_response_motion_sensor_data *data,
- struct motion_sensor_t *sensor,
- uint32_t timestamp)
-{
- int sensor_num = sensor - motion_sensors;
- int rc;
- int temperature;
- struct online_calib_data *calib_data;
- fpv3_t fdata;
- bool is_spoofed = IS_ENABLED(CONFIG_ONLINE_CALIB_SPOOF_MODE) &&
- (sensor->flags & MOTIONSENSE_FLAG_IN_SPOOF_MODE);
- bool has_new_calibration_values = false;
-
- /* Convert data to fp. */
- data_int16_to_fp(sensor, data->data, fdata);
-
- calib_data = sensor->online_calib_data;
- switch (sensor->type) {
- case MOTIONSENSE_TYPE_ACCEL: {
- struct accel_cal *cal =
- (struct accel_cal *)(calib_data->type_specific_data);
-
- if (is_spoofed) {
- /* Copy the data to the calibration result. */
- cal->bias[X] = fdata[X];
- cal->bias[Y] = fdata[Y];
- cal->bias[Z] = fdata[Z];
- has_new_calibration_values = true;
- } else {
- /* Possibly update the gyroscope calibration. */
- update_gyro_cal(sensor, fdata, timestamp);
-
- /*
- * Temperature is required for accelerometer
- * calibration.
- */
- rc = get_temperature(sensor, &temperature);
- if (rc != EC_SUCCESS)
- return rc;
-
- has_new_calibration_values = accel_cal_accumulate(
- cal, timestamp, fdata[X], fdata[Y], fdata[Z],
- temperature);
- }
-
- if (has_new_calibration_values) {
- mutex_lock(&g_calib_cache_mutex);
- /* Convert result to the right scale. */
- data_fp_to_int16(sensor, cal->bias, calib_data->cache);
- /* Set valid and dirty. */
- sensor_calib_cache_valid_map |= BIT(sensor_num);
- sensor_calib_cache_dirty_map |= BIT(sensor_num);
- mutex_unlock(&g_calib_cache_mutex);
- /* Notify the AP. */
- mkbp_send_event(EC_MKBP_EVENT_ONLINE_CALIBRATION);
- }
- break;
- }
- case MOTIONSENSE_TYPE_MAG: {
- struct mag_cal_t *cal =
- (struct mag_cal_t *)(calib_data->type_specific_data);
- int idata[] = {
- (int)data->data[X],
- (int)data->data[Y],
- (int)data->data[Z],
- };
-
- if (is_spoofed) {
- /* Copy the data to the calibration result. */
- cal->bias[X] = INT_TO_FP(idata[X]);
- cal->bias[Y] = INT_TO_FP(idata[Y]);
- cal->bias[Z] = INT_TO_FP(idata[Z]);
- has_new_calibration_values = true;
- } else {
- /* Possibly update the gyroscope calibration. */
- update_gyro_cal(sensor, fdata, timestamp);
-
- has_new_calibration_values = mag_cal_update(cal, idata);
- }
-
- if (has_new_calibration_values) {
- mutex_lock(&g_calib_cache_mutex);
- /* Copy the values */
- calib_data->cache[X] = cal->bias[X];
- calib_data->cache[Y] = cal->bias[Y];
- calib_data->cache[Z] = cal->bias[Z];
- /* Set valid and dirty. */
- sensor_calib_cache_valid_map |= BIT(sensor_num);
- sensor_calib_cache_dirty_map |= BIT(sensor_num);
- mutex_unlock(&g_calib_cache_mutex);
- /* Notify the AP. */
- mkbp_send_event(EC_MKBP_EVENT_ONLINE_CALIBRATION);
- }
- break;
- }
- case MOTIONSENSE_TYPE_GYRO: {
- if (is_spoofed) {
- /*
- * Gyroscope uses fdata to store the calibration
- * result, so there's no need to copy anything.
- */
- has_new_calibration_values = true;
- } else {
- struct gyro_cal_data *gyro_cal_data =
- (struct gyro_cal_data *)
- calib_data->type_specific_data;
- struct gyro_cal *gyro_cal = &gyro_cal_data->gyro_cal;
-
- /* Temperature is required for gyro calibration. */
- rc = get_temperature(sensor, &temperature);
- if (rc != EC_SUCCESS)
- return rc;
-
- /* Update gyroscope calibration. */
- gyro_cal_update_gyro(gyro_cal, timestamp, fdata[X],
- fdata[Y], fdata[Z], temperature);
- has_new_calibration_values =
- check_gyro_cal_new_bias(sensor, fdata);
- }
-
- if (has_new_calibration_values)
- set_gyro_cal_cache_values(sensor, fdata);
- break;
- }
- default:
- break;
- }
-
- return EC_SUCCESS;
-}
diff --git a/common/pd_log.c b/common/pd_log.c
deleted file mode 100644
index 3708aad72e..0000000000
--- a/common/pd_log.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/* Copyright 2014 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.
- */
-
-#include "charge_manager.h"
-#include "console.h"
-#include "event_log.h"
-#include "host_command.h"
-#include "timer.h"
-#include "usb_pd.h"
-#include "util.h"
-
-/*
- * Ensure PD logging parameters are compatible with the generic logging
- * framework that we're calling into.
- */
-BUILD_ASSERT(sizeof(struct ec_response_pd_log) ==
- sizeof(struct event_log_entry));
-BUILD_ASSERT(PD_LOG_SIZE_MASK == EVENT_LOG_SIZE_MASK);
-BUILD_ASSERT(PD_LOG_TIMESTAMP_SHIFT == EVENT_LOG_TIMESTAMP_SHIFT);
-BUILD_ASSERT(PD_EVENT_NO_ENTRY == EVENT_LOG_NO_ENTRY);
-
-void pd_log_event(uint8_t type, uint8_t size_port,
- uint16_t data, void *payload)
-{
- uint32_t timestamp = get_time().val >> PD_LOG_TIMESTAMP_SHIFT;
-
- log_add_event(type, size_port, data, payload, timestamp);
-}
-
-#ifdef HAS_TASK_HOSTCMD
-
-/* number of accessory entries we have queued since last check */
-static volatile int incoming_logs;
-
-void pd_log_recv_vdm(int port, int cnt, uint32_t *payload)
-{
- struct ec_response_pd_log *r = (void *)&payload[1];
- /* update port number from MCU point of view */
- size_t size = PD_LOG_SIZE(r->size_port);
- uint8_t size_port = PD_LOG_PORT_SIZE(port, size);
- uint32_t timestamp;
-
- if ((cnt < 2 + DIV_ROUND_UP(size, sizeof(uint32_t))) ||
- !(payload[0] & VDO_SRC_RESPONDER))
- /* Not a proper log entry, bail out */
- return;
-
- if (r->type != PD_EVENT_NO_ENTRY) {
- timestamp = (get_time().val >> PD_LOG_TIMESTAMP_SHIFT)
- - r->timestamp;
- log_add_event(r->type, size_port, r->data, r->payload,
- timestamp);
- /* record that we have enqueued new content */
- incoming_logs++;
- }
-}
-
-/* we are a PD MCU/EC, send back the events to the host */
-static enum ec_status hc_pd_get_log_entry(struct host_cmd_handler_args *args)
-{
- struct ec_response_pd_log *r = args->response;
-
-dequeue_retry:
- args->response_size = log_dequeue_event((struct event_log_entry *)r);
- /* if the MCU log no longer has entries, try connected accessories */
- if (r->type == PD_EVENT_NO_ENTRY) {
- int i, res;
- incoming_logs = 0;
- for (i = 0; i < board_get_usb_pd_port_count(); ++i) {
- /* only accessories who knows Google logging format */
- if (pd_get_identity_vid(i) != USB_VID_GOOGLE)
- continue;
- res = pd_fetch_acc_log_entry(i);
- if (res == EC_RES_BUSY) /* host should retry */
- return EC_RES_BUSY;
- }
- /* we have received new entries from an accessory */
- if (incoming_logs)
- goto dequeue_retry;
- /* else the current entry is already "PD_EVENT_NO_ENTRY" */
- }
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PD_GET_LOG_ENTRY,
- hc_pd_get_log_entry,
- EC_VER_MASK(0));
-
-static enum ec_status hc_pd_write_log_entry(struct host_cmd_handler_args *args)
-{
- const struct ec_params_pd_write_log_entry *p = args->params;
- uint8_t type = p->type;
- uint8_t port = p->port;
-
- if (type < PD_EVENT_MCU_BASE || type >= PD_EVENT_ACC_BASE)
- return EC_RES_INVALID_PARAM;
- if (port > 0 && port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- switch (type) {
- /* Charge event: Log data for all ports */
- case PD_EVENT_MCU_CHARGE:
-#ifdef CONFIG_CHARGE_MANAGER
- charge_manager_save_log(port);
-#endif
- break;
-
- /* Other events: no extra data, just log event type + port */
- case PD_EVENT_MCU_CONNECT:
- case PD_EVENT_MCU_BOARD_CUSTOM:
- default:
- pd_log_event(type, PD_LOG_PORT_SIZE(port, 0), 0, NULL);
- break;
- }
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PD_WRITE_LOG_ENTRY,
- hc_pd_write_log_entry,
- EC_VER_MASK(0));
-#else /* !HAS_TASK_HOSTCMD */
-/* we are a PD accessory, send back the events as a VDM (VDO_CMD_GET_LOG) */
-int pd_vdm_get_log_entry(uint32_t *payload)
-{
- struct ec_response_pd_log *r = (void *)&payload[1];
- int byte_size;
-
- byte_size = log_dequeue_event((struct event_log_entry *)r);
-
- return 1 + DIV_ROUND_UP(byte_size, sizeof(uint32_t));
-}
-#endif /* !HAS_TASK_HOSTCMD */
diff --git a/common/peci.c b/common/peci.c
deleted file mode 100644
index e0f03c95dd..0000000000
--- a/common/peci.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/* Copyright 2019 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.
- */
-
-/* PECI interface for Chrome EC */
-
-#include "chipset.h"
-#include "console.h"
-#include "peci.h"
-#include "util.h"
-
-static int peci_get_cpu_temp(int *cpu_temp)
-{
- int rv;
- uint8_t r_buf[PECI_GET_TEMP_READ_LENGTH] = {0};
- struct peci_data peci = {
- .cmd_code = PECI_CMD_GET_TEMP,
- .addr = PECI_TARGET_ADDRESS,
- .w_len = PECI_GET_TEMP_WRITE_LENGTH,
- .r_len = PECI_GET_TEMP_READ_LENGTH,
- .w_buf = NULL,
- .r_buf = r_buf,
- .timeout_us = PECI_GET_TEMP_TIMEOUT_US,
- };
-
- rv = peci_transaction(&peci);
- if (rv)
- return rv;
-
- /* Get relative raw data of temperature. */
- *cpu_temp = (r_buf[1] << 8) | r_buf[0];
-
- /* Convert relative raw data to degrees C. */
- *cpu_temp = ((*cpu_temp ^ 0xFFFF) + 1) >> 6;
-
- /*
- * When the AP transitions into S0, it is possible, depending on the
- * timing of the PECI sample, to read an invalid temperature. This is
- * very rare, but when it does happen the temperature returned is
- * greater than or equal to CONFIG_PECI_TJMAX.
- */
- if (*cpu_temp >= CONFIG_PECI_TJMAX)
- return EC_ERROR_UNKNOWN;
-
- /* temperature in K */
- *cpu_temp = CONFIG_PECI_TJMAX - *cpu_temp + 273;
-
- return EC_SUCCESS;
-}
-
-int peci_temp_sensor_get_val(int idx, int *temp_ptr)
-{
- int i, rv;
-
- if (!chipset_in_state(CHIPSET_STATE_ON | CHIPSET_STATE_STANDBY))
- return EC_ERROR_NOT_POWERED;
-
- /*
- * Retry reading PECI CPU temperature if the first sample is
- * invalid or failed to obtain.
- */
- for (i = 0; i < 2; i++) {
- rv = peci_get_cpu_temp(temp_ptr);
- if (!rv)
- break;
- }
-
- return rv;
-}
-
-/*****************************************************************************/
-/* Console commands */
-#ifdef CONFIG_CMD_PECI
-static int peci_cmd(int argc, char **argv)
-{
- uint8_t r_buf[PECI_READ_DATA_FIFO_SIZE] = {0};
- uint8_t w_buf[PECI_WRITE_DATA_FIFO_SIZE] = {0};
- struct peci_data peci = {
- .w_buf = w_buf,
- .r_buf = r_buf,
- };
-
- int param;
- char *e;
-
- if ((argc < 6) || (argc > 8))
- return EC_ERROR_PARAM_COUNT;
-
- peci.addr = strtoi(argv[1], &e, 0);
- if (*e)
- return EC_ERROR_PARAM1;
-
- peci.w_len = strtoi(argv[2], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2;
-
- peci.r_len = strtoi(argv[3], &e, 0);
- if (*e)
- return EC_ERROR_PARAM3;
-
- peci.cmd_code = strtoi(argv[4], &e, 0);
- if (*e)
- return EC_ERROR_PARAM4;
-
- peci.timeout_us = strtoi(argv[5], &e, 0);
- if (*e)
- return EC_ERROR_PARAM5;
-
- if (argc > 6) {
- param = strtoi(argv[6], &e, 0);
- if (*e)
- return EC_ERROR_PARAM6;
-
- /* MSB of parameter */
- w_buf[3] = (uint8_t)(param >> 24);
- /* LSB of parameter */
- w_buf[2] = (uint8_t)(param >> 16);
- /* Index */
- w_buf[1] = (uint8_t)(param >> 8);
- /* Host ID[7:1] & Retry[0] */
- w_buf[0] = (uint8_t)(param >> 0);
-
- if (argc > 7) {
- param = strtoi(argv[7], &e, 0);
- if (*e)
- return EC_ERROR_PARAM7;
-
- /* Data (1, 2 or 4 bytes) */
- w_buf[7] = (uint8_t)(param >> 24);
- w_buf[6] = (uint8_t)(param >> 16);
- w_buf[5] = (uint8_t)(param >> 8);
- w_buf[4] = (uint8_t)(param >> 0);
- }
- } else {
- peci.w_len = 0x00;
- }
-
- if (peci_transaction(&peci)) {
- ccprintf("PECI transaction error\n");
- return EC_ERROR_UNKNOWN;
- }
- ccprintf("PECI read data: %ph\n", HEX_BUF(r_buf, peci.r_len));
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(peci, peci_cmd,
- "addr wlen rlen cmd timeout(us)",
- "PECI command");
-
-static int command_peci_temp(int argc, char **argv)
-{
- int t;
-
- if (peci_get_cpu_temp(&t) != EC_SUCCESS) {
- ccprintf("PECI get cpu temp error\n");
- return EC_ERROR_UNKNOWN;
- }
-
- ccprintf("CPU temp: %d K, %d C\n", t, K_TO_C(t));
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(pecitemp, command_peci_temp,
- NULL,
- "Print CPU temperature");
-#endif /* CONFIG_CMD_PECI */
diff --git a/common/peripheral_charger.c b/common/peripheral_charger.c
deleted file mode 100644
index 0a597ad6bd..0000000000
--- a/common/peripheral_charger.c
+++ /dev/null
@@ -1,740 +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.
- */
-
-#include "atomic.h"
-#include "chipset.h"
-#include "common.h"
-#include "device_event.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "mkbp_event.h"
-#include "peripheral_charger.h"
-#include "queue.h"
-#include "stdbool.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-
-/* Peripheral Charge Manager */
-
-#define CPRINTS(fmt, args...) cprints(CC_PCHG, "PCHG: " fmt, ##args)
-
-/* Currently only used for FW update. */
-static uint32_t pchg_host_events;
-
-static void pchg_queue_event(struct pchg *ctx, enum pchg_event event)
-{
- mutex_lock(&ctx->mtx);
- if (queue_add_unit(&ctx->events, &event) == 0) {
- ctx->dropped_event_count++;
- CPRINTS("ERR: Queue is full");
- }
- mutex_unlock(&ctx->mtx);
-}
-
-static void _send_host_event(const struct pchg *ctx, uint32_t event)
-{
- int port = PCHG_CTX_TO_PORT(ctx);
-
- atomic_or(&pchg_host_events, event | port << EC_MKBP_PCHG_PORT_SHIFT);
- mkbp_send_event(EC_MKBP_EVENT_PCHG);
-}
-
-static const char *_text_state(enum pchg_state state)
-{
- /* TODO: Use "S%d" for normal build. */
- static const char * const state_names[] = EC_PCHG_STATE_TEXT;
- BUILD_ASSERT(ARRAY_SIZE(state_names) == PCHG_STATE_COUNT);
-
- if (state >= sizeof(state_names))
- return "UNDEF";
-
- return state_names[state];
-}
-
-static const char *_text_event(enum pchg_event event)
-{
- /* TODO: Use "S%d" for normal build. */
- static const char * const event_names[] = {
- [PCHG_EVENT_NONE] = "NONE",
- [PCHG_EVENT_IRQ] = "IRQ",
- [PCHG_EVENT_RESET] = "RESET",
- [PCHG_EVENT_INITIALIZED] = "INITIALIZED",
- [PCHG_EVENT_ENABLED] = "ENABLED",
- [PCHG_EVENT_DISABLED] = "DISABLED",
- [PCHG_EVENT_DEVICE_DETECTED] = "DEVICE_DETECTED",
- [PCHG_EVENT_DEVICE_CONNECTED] = "DEVICE_CONNECTED",
- [PCHG_EVENT_DEVICE_LOST] = "DEVICE_LOST",
- [PCHG_EVENT_CHARGE_STARTED] = "CHARGE_STARTED",
- [PCHG_EVENT_CHARGE_UPDATE] = "CHARGE_UPDATE",
- [PCHG_EVENT_CHARGE_ENDED] = "CHARGE_ENDED",
- [PCHG_EVENT_CHARGE_STOPPED] = "CHARGE_STOPPED",
- [PCHG_EVENT_UPDATE_OPENED] = "UPDATE_OPENED",
- [PCHG_EVENT_UPDATE_CLOSED] = "UPDATE_CLOSED",
- [PCHG_EVENT_UPDATE_WRITTEN] = "UPDATE_WRITTEN",
- [PCHG_EVENT_IN_NORMAL] = "IN_NORMAL",
- [PCHG_EVENT_CHARGE_ERROR] = "CHARGE_ERROR",
- [PCHG_EVENT_UPDATE_ERROR] = "UPDATE_ERROR",
- [PCHG_EVENT_OTHER_ERROR] = "OTHER_ERROR",
- [PCHG_EVENT_ENABLE] = "ENABLE",
- [PCHG_EVENT_DISABLE] = "DISABLE",
- [PCHG_EVENT_UPDATE_OPEN] = "UPDATE_OPEN",
- [PCHG_EVENT_UPDATE_WRITE] = "UPDATE_WRITE",
- [PCHG_EVENT_UPDATE_CLOSE] = "UPDATE_CLOSE",
- };
- BUILD_ASSERT(ARRAY_SIZE(event_names) == PCHG_EVENT_COUNT);
-
- if (event >= sizeof(event_names))
- return "UNDEF";
-
- return event_names[event];
-}
-
-static void _clear_port(struct pchg *ctx)
-{
- mutex_lock(&ctx->mtx);
- queue_init(&ctx->events);
- mutex_unlock(&ctx->mtx);
- atomic_clear(&ctx->irq);
- ctx->battery_percent = 0;
- ctx->error = 0;
- ctx->update.data_ready = 0;
-}
-
-static enum pchg_state pchg_reset(struct pchg *ctx)
-{
- enum pchg_state state = PCHG_STATE_RESET;
- int rv;
-
- /*
- * In case we get asynchronous reset, clear port though it's redundant
- * for a synchronous reset.
- */
- _clear_port(ctx);
-
- if (ctx->mode == PCHG_MODE_NORMAL) {
- rv = ctx->cfg->drv->init(ctx);
- if (rv == EC_SUCCESS) {
- state = PCHG_STATE_INITIALIZED;
- pchg_queue_event(ctx, PCHG_EVENT_ENABLE);
- } else if (rv != EC_SUCCESS_IN_PROGRESS) {
- CPRINTS("ERR: Failed to reset to normal mode");
- }
- } else {
- state = PCHG_STATE_DOWNLOAD;
- pchg_queue_event(ctx, PCHG_EVENT_UPDATE_OPEN);
- }
-
- return state;
-}
-
-static void pchg_state_reset(struct pchg *ctx)
-{
- switch (ctx->event) {
- case PCHG_EVENT_RESET:
- ctx->state = pchg_reset(ctx);
- break;
- case PCHG_EVENT_IN_NORMAL:
- ctx->state = PCHG_STATE_INITIALIZED;
- pchg_queue_event(ctx, PCHG_EVENT_ENABLE);
- break;
- default:
- break;
- }
-}
-
-static void pchg_state_initialized(struct pchg *ctx)
-{
- int rv;
-
- if (ctx->event == PCHG_EVENT_ENABLE)
- ctx->error &= ~PCHG_ERROR_HOST;
-
- /* Spin in INITIALIZED until error condition is cleared. */
- if (ctx->error)
- return;
-
- switch (ctx->event) {
- case PCHG_EVENT_RESET:
- ctx->state = pchg_reset(ctx);
- break;
- case PCHG_EVENT_ENABLE:
- rv = ctx->cfg->drv->enable(ctx, true);
- if (rv == EC_SUCCESS)
- ctx->state = PCHG_STATE_ENABLED;
- else if (rv != EC_SUCCESS_IN_PROGRESS)
- CPRINTS("ERR: Failed to enable");
- break;
- case PCHG_EVENT_ENABLED:
- ctx->state = PCHG_STATE_ENABLED;
- break;
- default:
- break;
- }
-}
-
-static void pchg_state_enabled(struct pchg *ctx)
-{
- int rv;
-
- switch (ctx->event) {
- case PCHG_EVENT_RESET:
- ctx->state = pchg_reset(ctx);
- break;
- case PCHG_EVENT_DISABLE:
- ctx->error |= PCHG_ERROR_HOST;
- rv = ctx->cfg->drv->enable(ctx, false);
- if (rv == EC_SUCCESS)
- ctx->state = PCHG_STATE_INITIALIZED;
- else if (rv != EC_SUCCESS_IN_PROGRESS)
- CPRINTS("ERR: Failed to disable");
- break;
- case PCHG_EVENT_DISABLED:
- ctx->state = PCHG_STATE_INITIALIZED;
- break;
- case PCHG_EVENT_DEVICE_DETECTED:
- ctx->state = PCHG_STATE_DETECTED;
- break;
- case PCHG_EVENT_DEVICE_CONNECTED:
- /*
- * Proactively query SOC in case charging info won't be sent
- * because device is already charged.
- */
- ctx->cfg->drv->get_soc(ctx);
- ctx->state = PCHG_STATE_CONNECTED;
- break;
- default:
- break;
- }
-}
-
-static void pchg_state_detected(struct pchg *ctx)
-{
- int rv;
-
- switch (ctx->event) {
- case PCHG_EVENT_RESET:
- ctx->state = pchg_reset(ctx);
- break;
- case PCHG_EVENT_DISABLE:
- ctx->error |= PCHG_ERROR_HOST;
- rv = ctx->cfg->drv->enable(ctx, false);
- if (rv == EC_SUCCESS)
- ctx->state = PCHG_STATE_INITIALIZED;
- else if (rv != EC_SUCCESS_IN_PROGRESS)
- CPRINTS("ERR: Failed to disable");
- break;
- case PCHG_EVENT_DISABLED:
- ctx->state = PCHG_STATE_INITIALIZED;
- break;
- case PCHG_EVENT_DEVICE_CONNECTED:
- /*
- * Proactively query SOC in case charging info won't be sent
- * because device is already charged.
- */
- ctx->cfg->drv->get_soc(ctx);
- ctx->state = PCHG_STATE_CONNECTED;
- break;
- case PCHG_EVENT_DEVICE_LOST:
- ctx->battery_percent = 0;
- ctx->state = PCHG_STATE_ENABLED;
- break;
- default:
- break;
- }
-}
-
-static void pchg_state_connected(struct pchg *ctx)
-{
- int rv;
-
- switch (ctx->event) {
- case PCHG_EVENT_RESET:
- ctx->state = pchg_reset(ctx);
- break;
- case PCHG_EVENT_DISABLE:
- ctx->error |= PCHG_ERROR_HOST;
- rv = ctx->cfg->drv->enable(ctx, false);
- if (rv == EC_SUCCESS)
- ctx->state = PCHG_STATE_INITIALIZED;
- else if (rv != EC_SUCCESS_IN_PROGRESS)
- CPRINTS("ERR: Failed to disable");
- break;
- case PCHG_EVENT_DISABLED:
- ctx->state = PCHG_STATE_INITIALIZED;
- break;
- case PCHG_EVENT_CHARGE_STARTED:
- ctx->state = PCHG_STATE_CHARGING;
- break;
- case PCHG_EVENT_DEVICE_LOST:
- ctx->battery_percent = 0;
- ctx->state = PCHG_STATE_ENABLED;
- break;
- case PCHG_EVENT_CHARGE_ERROR:
- ctx->state = PCHG_STATE_INITIALIZED;
- break;
- default:
- break;
- }
-}
-
-static void pchg_state_charging(struct pchg *ctx)
-{
- int rv;
-
- switch (ctx->event) {
- case PCHG_EVENT_RESET:
- ctx->state = pchg_reset(ctx);
- break;
- case PCHG_EVENT_DISABLE:
- ctx->error |= PCHG_ERROR_HOST;
- rv = ctx->cfg->drv->enable(ctx, false);
- if (rv == EC_SUCCESS)
- ctx->state = PCHG_STATE_INITIALIZED;
- else if (rv != EC_SUCCESS_IN_PROGRESS)
- CPRINTS("ERR: Failed to disable");
- break;
- case PCHG_EVENT_DISABLED:
- ctx->state = PCHG_STATE_INITIALIZED;
- break;
- case PCHG_EVENT_CHARGE_UPDATE:
- break;
- case PCHG_EVENT_DEVICE_LOST:
- ctx->battery_percent = 0;
- ctx->state = PCHG_STATE_ENABLED;
- break;
- case PCHG_EVENT_CHARGE_ERROR:
- ctx->state = PCHG_STATE_INITIALIZED;
- break;
- case PCHG_EVENT_CHARGE_ENDED:
- case PCHG_EVENT_CHARGE_STOPPED:
- ctx->state = PCHG_STATE_CONNECTED;
- break;
- default:
- break;
- }
-}
-
-static void pchg_state_download(struct pchg *ctx)
-{
- int rv;
-
- switch (ctx->event) {
- case PCHG_EVENT_RESET:
- ctx->state = pchg_reset(ctx);
- break;
- case PCHG_EVENT_UPDATE_OPEN:
- rv = ctx->cfg->drv->update_open(ctx);
- if (rv == EC_SUCCESS) {
- ctx->state = PCHG_STATE_DOWNLOADING;
- } else if (rv != EC_SUCCESS_IN_PROGRESS) {
- _send_host_event(ctx, EC_MKBP_PCHG_UPDATE_ERROR);
- CPRINTS("ERR: Failed to open");
- }
- break;
- case PCHG_EVENT_UPDATE_OPENED:
- ctx->state = PCHG_STATE_DOWNLOADING;
- _send_host_event(ctx, EC_MKBP_PCHG_UPDATE_OPENED);
- break;
- case PCHG_EVENT_UPDATE_ERROR:
- _send_host_event(ctx, EC_MKBP_PCHG_UPDATE_ERROR);
- break;
- default:
- break;
- }
-}
-
-static void pchg_state_downloading(struct pchg *ctx)
-{
- int rv;
-
- switch (ctx->event) {
- case PCHG_EVENT_RESET:
- ctx->state = pchg_reset(ctx);
- break;
- case PCHG_EVENT_UPDATE_WRITE:
- if (ctx->update.data_ready == 0)
- break;
- rv = ctx->cfg->drv->update_write(ctx);
- if (rv != EC_SUCCESS && rv != EC_SUCCESS_IN_PROGRESS) {
- _send_host_event(ctx, EC_MKBP_PCHG_UPDATE_ERROR);
- CPRINTS("ERR: Failed to write");
- }
- break;
- case PCHG_EVENT_UPDATE_WRITTEN:
- ctx->update.data_ready = 0;
- _send_host_event(ctx, EC_MKBP_PCHG_WRITE_COMPLETE);
- break;
- case PCHG_EVENT_UPDATE_CLOSE:
- rv = ctx->cfg->drv->update_close(ctx);
- if (rv == EC_SUCCESS) {
- ctx->state = PCHG_STATE_DOWNLOAD;
- } else if (rv != EC_SUCCESS_IN_PROGRESS) {
- _send_host_event(ctx, EC_MKBP_PCHG_UPDATE_ERROR);
- CPRINTS("ERR: Failed to close");
- }
- break;
- case PCHG_EVENT_UPDATE_CLOSED:
- ctx->state = PCHG_STATE_DOWNLOAD;
- _send_host_event(ctx, EC_MKBP_PCHG_UPDATE_CLOSED);
- break;
- case PCHG_EVENT_UPDATE_ERROR:
- CPRINTS("ERR: Failed to update");
- _send_host_event(ctx, EC_MKBP_PCHG_UPDATE_ERROR);
- break;
- default:
- break;
- }
-}
-
-static int pchg_run(struct pchg *ctx)
-{
- enum pchg_state previous_state = ctx->state;
- uint8_t previous_battery = ctx->battery_percent;
- int port = PCHG_CTX_TO_PORT(ctx);
- int rv;
-
- mutex_lock(&ctx->mtx);
- if (!queue_remove_unit(&ctx->events, &ctx->event)) {
- mutex_unlock(&ctx->mtx);
- CPRINTS("P%d No event in queue", port);
- return 0;
- }
- mutex_unlock(&ctx->mtx);
-
- CPRINTS("P%d Run in STATE_%s for EVENT_%s", port,
- _text_state(ctx->state), _text_event(ctx->event));
-
- if (ctx->event == PCHG_EVENT_IRQ) {
- rv = ctx->cfg->drv->get_event(ctx);
- if (rv) {
- CPRINTS("ERR: Failed to get event (%d)", rv);
- return 0;
- }
- CPRINTS(" EVENT_%s", _text_event(ctx->event));
- }
-
- if (ctx->event == PCHG_EVENT_NONE)
- return 0;
-
- switch (ctx->state) {
- case PCHG_STATE_RESET:
- pchg_state_reset(ctx);
- break;
- case PCHG_STATE_INITIALIZED:
- pchg_state_initialized(ctx);
- break;
- case PCHG_STATE_ENABLED:
- pchg_state_enabled(ctx);
- break;
- case PCHG_STATE_DETECTED:
- pchg_state_detected(ctx);
- break;
- case PCHG_STATE_CONNECTED:
- pchg_state_connected(ctx);
- break;
- case PCHG_STATE_CHARGING:
- pchg_state_charging(ctx);
- break;
- case PCHG_STATE_DOWNLOAD:
- pchg_state_download(ctx);
- break;
- case PCHG_STATE_DOWNLOADING:
- pchg_state_downloading(ctx);
- break;
- default:
- CPRINTS("ERR: Unknown state (%d)", ctx->state);
- return 0;
- }
-
- if (previous_state != ctx->state)
- CPRINTS("->STATE_%s", _text_state(ctx->state));
-
- if (ctx->battery_percent != previous_battery)
- CPRINTS("Battery %u%%", ctx->battery_percent);
-
- /*
- * Notify the host of
- * - [S0] Charge update with SoC change and all other events.
- * - [S3/S0IX] Device attach or detach (for wake-up)
- * - [S5/G3] No events.
- */
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
- return 0;
-
- if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND))
- return (ctx->event == PCHG_EVENT_DEVICE_DETECTED)
- || (ctx->event == PCHG_EVENT_DEVICE_LOST);
-
- if (ctx->event == PCHG_EVENT_CHARGE_UPDATE)
- return ctx->battery_percent != previous_battery;
-
- return ctx->event != PCHG_EVENT_NONE;
-}
-
-void pchg_irq(enum gpio_signal signal)
-{
- struct pchg *ctx;
- int i;
-
- for (i = 0; i < pchg_count; i++) {
- ctx = &pchgs[i];
- if (signal == ctx->cfg->irq_pin) {
- ctx->irq = 1;
- task_wake(TASK_ID_PCHG);
- return;
- }
- }
-}
-
-
-static void pchg_suspend_complete(void)
-{
- CPRINTS("%s", __func__);
- device_enable_event(EC_DEVICE_EVENT_WLC);
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND_COMPLETE, pchg_suspend_complete,
- HOOK_PRIO_DEFAULT);
-
-static void pchg_startup(void)
-{
- struct pchg *ctx;
- int p;
-
- CPRINTS("%s", __func__);
-
- for (p = 0; p < pchg_count; p++) {
- ctx = &pchgs[p];
- _clear_port(ctx);
- ctx->mode = PCHG_MODE_NORMAL;
- ctx->cfg->drv->reset(ctx);
- gpio_enable_interrupt(ctx->cfg->irq_pin);
- }
-
- task_wake(TASK_ID_PCHG);
-}
-DECLARE_HOOK(HOOK_CHIPSET_STARTUP, pchg_startup, HOOK_PRIO_DEFAULT);
-
-static void pchg_shutdown(void)
-{
- struct pchg *ctx;
- int p;
-
- CPRINTS("%s", __func__);
-
- for (p = 0; p < pchg_count; p++) {
- ctx = &pchgs[0];
- gpio_disable_interrupt(ctx->cfg->irq_pin);
- }
-}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pchg_shutdown, HOOK_PRIO_DEFAULT);
-
-void pchg_task(void *u)
-{
- struct pchg *ctx;
- int p;
-
- if (chipset_in_state(CHIPSET_STATE_ON))
- /* We are here after power-on (because of late sysjump). */
- pchg_startup();
-
- while (true) {
- /* Process pending events for all ports. */
- int rv = 0;
-
- for (p = 0; p < pchg_count; p++) {
- ctx = &pchgs[p];
- do {
- if (atomic_clear(&ctx->irq))
- pchg_queue_event(ctx, PCHG_EVENT_IRQ);
- rv |= pchg_run(ctx);
- } while (queue_count(&ctx->events));
- }
-
- /* Send one host event for all ports. */
- if (rv)
- device_set_single_event(EC_DEVICE_EVENT_WLC);
-
- task_wait_event(-1);
- }
-}
-
-static enum ec_status hc_pchg_count(struct host_cmd_handler_args *args)
-{
- struct ec_response_pchg_count *r = args->response;
-
- r->port_count = pchg_count;
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PCHG_COUNT, hc_pchg_count, EC_VER_MASK(0));
-
-#define HCPRINTS(fmt, args...) cprints(CC_PCHG, "HC:PCHG: " fmt, ##args)
-
-static enum ec_status hc_pchg(struct host_cmd_handler_args *args)
-{
- const struct ec_params_pchg *p = args->params;
- struct ec_response_pchg *r = args->response;
- int port = p->port;
- struct pchg *ctx;
-
- if (port >= pchg_count)
- return EC_RES_INVALID_PARAM;
-
- ctx = &pchgs[port];
-
- if (ctx->state == PCHG_STATE_CONNECTED
- && ctx->battery_percent >= ctx->cfg->full_percent)
- r->state = PCHG_STATE_FULL;
- else
- r->state = ctx->state;
-
- r->battery_percentage = ctx->battery_percent;
- r->error = ctx->error;
- r->fw_version = ctx->fw_version;
- r->dropped_event_count = ctx->dropped_event_count;
-
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PCHG, hc_pchg, EC_VER_MASK(1));
-
-int pchg_get_next_event(uint8_t *out)
-{
- uint32_t events = atomic_clear(&pchg_host_events);
-
- memcpy(out, &events, sizeof(events));
-
- return sizeof(events);
-}
-DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_PCHG, pchg_get_next_event);
-
-static enum ec_status hc_pchg_update(struct host_cmd_handler_args *args)
-{
- const struct ec_params_pchg_update *p = args->params;
- struct ec_response_pchg_update *r = args->response;
- int port = p->port;
- struct pchg *ctx;
-
- if (port >= pchg_count)
- return EC_RES_INVALID_PARAM;
-
- ctx = &pchgs[port];
-
- switch (p->cmd) {
- case EC_PCHG_UPDATE_CMD_RESET_TO_NORMAL:
- HCPRINTS("Resetting to normal mode");
-
- gpio_disable_interrupt(ctx->cfg->irq_pin);
- _clear_port(ctx);
- ctx->mode = PCHG_MODE_NORMAL;
- ctx->cfg->drv->reset(ctx);
- gpio_enable_interrupt(ctx->cfg->irq_pin);
- break;
-
- case EC_PCHG_UPDATE_CMD_OPEN:
- HCPRINTS("Resetting to download mode");
-
- gpio_disable_interrupt(ctx->cfg->irq_pin);
- _clear_port(ctx);
- ctx->mode = PCHG_MODE_DOWNLOAD;
- ctx->cfg->drv->reset(ctx);
- gpio_enable_interrupt(ctx->cfg->irq_pin);
-
- ctx->update.version = p->version;
- r->block_size = ctx->cfg->block_size;
- args->response_size = sizeof(*r);
- break;
-
- case EC_PCHG_UPDATE_CMD_WRITE:
- if (ctx->state != PCHG_STATE_DOWNLOADING)
- return EC_RES_ERROR;
- if (p->size > sizeof(ctx->update.data))
- return EC_RES_OVERFLOW;
- if (ctx->update.data_ready)
- return EC_RES_BUSY;
-
- HCPRINTS("Writing %u bytes to 0x%x", p->size, p->addr);
- ctx->update.addr = p->addr;
- ctx->update.size = p->size;
- memcpy(ctx->update.data, p->data, p->size);
- pchg_queue_event(ctx, PCHG_EVENT_UPDATE_WRITE);
- ctx->update.data_ready = 1;
- break;
-
- case EC_PCHG_UPDATE_CMD_CLOSE:
- if (ctx->state != PCHG_STATE_DOWNLOADING)
- return EC_RES_ERROR;
- if (ctx->update.data_ready)
- return EC_RES_BUSY;
-
- HCPRINTS("Closing update session (crc=0x%x)", p->crc32);
- ctx->update.crc32 = p->crc32;
- pchg_queue_event(ctx, PCHG_EVENT_UPDATE_CLOSE);
- break;
- default:
- return EC_RES_INVALID_PARAM;
- }
-
- task_wake(TASK_ID_PCHG);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PCHG_UPDATE, hc_pchg_update, EC_VER_MASK(0));
-
-static int cc_pchg(int argc, char **argv)
-{
- int port;
- char *end;
- struct pchg *ctx;
-
- if (argc < 2 || 4 < argc)
- return EC_ERROR_PARAM_COUNT;
-
- port = strtoi(argv[1], &end, 0);
- if (*end || port < 0 || port >= pchg_count)
- return EC_ERROR_PARAM1;
- ctx = &pchgs[port];
-
- if (argc == 2) {
- ccprintf("P%d STATE_%s EVENT_%s SOC=%d%%\n",
- port, _text_state(ctx->state), _text_event(ctx->event),
- ctx->battery_percent);
- ccprintf("error=0x%x dropped=%u fw_version=0x%x\n",
- ctx->error, ctx->dropped_event_count, ctx->fw_version);
- return EC_SUCCESS;
- }
-
- if (!strcasecmp(argv[2], "reset")) {
- if (argc == 3)
- ctx->mode = PCHG_MODE_NORMAL;
- else if (!strcasecmp(argv[3], "download"))
- ctx->mode = PCHG_MODE_DOWNLOAD;
- else
- return EC_ERROR_PARAM3;
- gpio_disable_interrupt(ctx->cfg->irq_pin);
- _clear_port(ctx);
- ctx->cfg->drv->reset(ctx);
- gpio_enable_interrupt(ctx->cfg->irq_pin);
- } else if (!strcasecmp(argv[2], "enable")) {
- pchg_queue_event(ctx, PCHG_EVENT_ENABLE);
- } else if (!strcasecmp(argv[2], "disable")) {
- pchg_queue_event(ctx, PCHG_EVENT_DISABLE);
- } else {
- return EC_ERROR_PARAM2;
- }
-
- task_wake(TASK_ID_PCHG);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(pchg, cc_pchg,
- "\n\t<port>"
- "\n\t<port> reset [download]"
- "\n\t<port> enable"
- "\n\t<port> disable",
- "Control peripheral chargers");
diff --git a/common/port80.c b/common/port80.c
deleted file mode 100644
index ab1f112112..0000000000
--- a/common/port80.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/* Copyright 2012 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.
- */
-
-/* Port 80 module for Chrome EC */
-
-#include "common.h"
-#include "console.h"
-#include "display_7seg.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "port80.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-
-#define CPRINTF(format, args...) cprintf(CC_PORT80, format, ## args)
-
-#ifdef CONFIG_PORT80_4_BYTE
-typedef uint32_t port80_code_t;
-#else
-typedef uint16_t port80_code_t;
-#endif
-static port80_code_t __bss_slow history[CONFIG_PORT80_HISTORY_LEN];
-static int __bss_slow writes; /* Number of port 80 writes so far */
-static uint16_t last_boot; /* Last code from previous boot */
-static int __bss_slow scroll;
-
-#ifdef CONFIG_BRINGUP
-#undef CONFIG_PORT80_PRINT_IN_INT
-#define CONFIG_PORT80_PRINT_IN_INT 1
-#endif
-
-static int print_in_int = CONFIG_PORT80_PRINT_IN_INT;
-
-static void port80_dump_buffer(void);
-DECLARE_DEFERRED(port80_dump_buffer);
-
-void port_80_write(int data)
-{
- /*
- * By default print_in_int is disabled if:
- * 1. CONFIG_BRINGUP is not defined
- * 2. CONFIG_PRINT_IN_INT is set to disable by default
- *
- * This is done to prevent printing in interrupt context. Boards can
- * enable this by either defining CONFIG_BRINGUP or enabling
- * CONFIG_PRINT_IN_INT in board configs.
- *
- * If at runtime, print_in_int is disabled, then this function will
- * schedule a deferred call 4 seconds after the last port80 write to
- * dump the current port80 buffer to EC console. This is to allow
- * developers to help debug BIOS progress by tracing port80 messages.
- */
- if (print_in_int)
- CPRINTF("%c[%pT Port 80: 0x%02x]",
- scroll ? '\n' : '\r', PRINTF_TIMESTAMP_NOW, data);
-
- hook_call_deferred(&port80_dump_buffer_data, 4 * SECOND);
-
- /* Save current port80 code if system is resetting */
- if (data == PORT_80_EVENT_RESET && writes) {
- port80_code_t prev = history[(writes-1) % ARRAY_SIZE(history)];
-
- /*
- * last_boot only reports 8-bit codes.
- * Ignore special event codes and 4-byte codes.
- */
- if (prev < 0x100)
- last_boot = prev;
- }
-
- history[writes % ARRAY_SIZE(history)] = data;
- writes++;
-}
-
-static void port80_dump_buffer(void)
-{
- int printed = 0;
- int i;
- int head, tail;
- int last_e = 0;
-
- /*
- * Print the port 80 writes so far, clipped to the length of our
- * history buffer.
- *
- * Technically, if a port 80 write comes in while we're printing this,
- * we could print an incorrect history. Probably not worth the
- * complexity to work around that.
- */
- head = writes;
- if (head > ARRAY_SIZE(history))
- tail = head - ARRAY_SIZE(history);
- else
- tail = 0;
-
- ccputs("Port 80 writes:");
- for (i = tail; i < head; i++) {
- int e = history[i % ARRAY_SIZE(history)];
- switch (e) {
- case PORT_80_EVENT_RESUME:
- ccprintf("\n(S3->S0)");
- printed = 0;
- break;
- case PORT_80_EVENT_RESET:
- ccprintf("\n(RESET)");
- printed = 0;
- break;
- default:
- if (!(printed++ % 20)) {
- ccputs("\n ");
- cflush();
- }
- ccprintf(" %02x", e);
- last_e = e;
- }
- }
- ccputs(" <--new\n");
-
- /* Displaying last port80 msg on 7-segment if it is enabled */
- if (IS_ENABLED(CONFIG_SEVEN_SEG_DISPLAY) && last_e)
- display_7seg_write(SEVEN_SEG_PORT80_DISPLAY, last_e);
-}
-
-/*****************************************************************************/
-/* Console commands */
-
-static int command_port80(int argc, char **argv)
-{
- /*
- * 'port80 scroll' toggles whether port 80 output begins with a newline
- * (scrolling) or CR (non-scrolling).
- */
- if (argc > 1) {
- if (!strcasecmp(argv[1], "scroll")) {
- scroll = !scroll;
- ccprintf("scroll %sabled\n", scroll ? "en" : "dis");
- return EC_SUCCESS;
- } else if (!strcasecmp(argv[1], "intprint")) {
- print_in_int = !print_in_int;
- ccprintf("printing in interrupt %sabled\n",
- print_in_int ? "en" : "dis");
- return EC_SUCCESS;
- } else if (!strcasecmp(argv[1], "flush")) {
- writes = 0;
- return EC_SUCCESS;
- } else {
- return EC_ERROR_PARAM1;
- }
- }
-
- port80_dump_buffer();
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(port80, command_port80,
- "[scroll | intprint | flush]",
- "Print port80 writes or toggle port80 scrolling");
-
-enum ec_status port80_last_boot(struct host_cmd_handler_args *args)
-{
- struct ec_response_port80_last_boot *r = args->response;
-
- args->response_size = sizeof(*r);
- r->code = last_boot;
-
- return EC_RES_SUCCESS;
-}
-
-enum ec_status port80_command_read(struct host_cmd_handler_args *args)
-{
- const struct ec_params_port80_read *p = args->params;
- uint32_t offset = p->read_buffer.offset;
- uint32_t entries = p->read_buffer.num_entries;
- int i;
- struct ec_response_port80_read *rsp = args->response;
-
- if (args->version == 0)
- return port80_last_boot(args);
-
- if (p->subcmd == EC_PORT80_GET_INFO) {
- rsp->get_info.writes = writes;
- rsp->get_info.history_size = ARRAY_SIZE(history);
- args->response_size = sizeof(rsp->get_info);
- return EC_RES_SUCCESS;
- } else if (p->subcmd == EC_PORT80_READ_BUFFER) {
- /* do not allow bad offset or size */
- if (offset >= ARRAY_SIZE(history) || entries == 0 ||
- entries > args->response_max)
- return EC_RES_INVALID_PARAM;
-
- for (i = 0; i < entries; i++) {
- uint16_t e = history[(i + offset) %
- ARRAY_SIZE(history)];
- rsp->data.codes[i] = e;
- }
-
- args->response_size = entries*sizeof(uint16_t);
- return EC_RES_SUCCESS;
- }
-
- return EC_RES_INVALID_PARAM;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PORT80_READ,
- port80_command_read,
- EC_VER_MASK(0) | EC_VER_MASK(1));
-
-static void port80_log_resume(void)
-{
- /* Store port 80 event so we know where resume happened */
- port_80_write(PORT_80_EVENT_RESUME);
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, port80_log_resume, HOOK_PRIO_DEFAULT);
diff --git a/common/power_button.c b/common/power_button.c
deleted file mode 100644
index 1ac3893492..0000000000
--- a/common/power_button.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/* Copyright 2013 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.
- */
-
-/* Power button module for Chrome EC */
-
-#include "button.h"
-#include "common.h"
-#include "console.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "keyboard_scan.h"
-#include "lid_switch.h"
-#include "power_button.h"
-#include "system.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_SWITCH, outstr)
-#define CPRINTS(format, args...) cprints(CC_SWITCH, format, ## args)
-
-/* By default the power button is active low */
-#ifndef CONFIG_POWER_BUTTON_FLAGS
-#define CONFIG_POWER_BUTTON_FLAGS 0
-#endif
-
-static int debounced_power_pressed; /* Debounced power button state */
-static int simulate_power_pressed;
-static volatile int power_button_is_stable = 1;
-
-static const struct button_config power_button = {
- .name = "power button",
- .gpio = GPIO_POWER_BUTTON_L,
- .debounce_us = BUTTON_DEBOUNCE_US,
- .flags = CONFIG_POWER_BUTTON_FLAGS,
-};
-
-int power_button_signal_asserted(void)
-{
- return !!(gpio_get_level(power_button.gpio)
- == (power_button.flags & BUTTON_FLAG_ACTIVE_HIGH) ? 1 : 0);
-}
-
-/**
- * Get raw power button signal state.
- *
- * @return 1 if power button is pressed, 0 if not pressed.
- */
-static int raw_power_button_pressed(void)
-{
- if (simulate_power_pressed)
- return 1;
-
-#ifndef CONFIG_POWER_BUTTON_IGNORE_LID
- /*
- * Always indicate power button released if the lid is closed.
- * This prevents waking the system if the device is squashed enough to
- * press the power button through the closed lid.
- */
- if (!lid_is_open())
- return 0;
-#endif
-
- return power_button_signal_asserted();
-}
-
-int power_button_is_pressed(void)
-{
- return debounced_power_pressed;
-}
-
-int power_button_wait_for_release(int timeout_us)
-{
- timestamp_t deadline;
- timestamp_t now = get_time();
-
- deadline.val = now.val + timeout_us;
-
- while (!power_button_is_stable || power_button_is_pressed()) {
- now = get_time();
- if (timeout_us >= 0 && timestamp_expired(deadline, &now)) {
- CPRINTS("%s not released in time", power_button.name);
- return EC_ERROR_TIMEOUT;
- }
- /*
- * We use task_wait_event() instead of usleep() here. It will
- * be woken up immediately if the power button is debouned and
- * changed. However, it is not guaranteed, like the cases that
- * the power button is debounced but not changed, or the power
- * button has not been debounced.
- */
- task_wait_event(MIN(power_button.debounce_us,
- deadline.val - now.val));
- }
-
- CPRINTS("%s released in time", power_button.name);
- return EC_SUCCESS;
-}
-
-/**
- * Handle power button initialization.
- */
-static void power_button_init(void)
-{
- if (raw_power_button_pressed())
- debounced_power_pressed = 1;
-
- /* Enable interrupts, now that we've initialized */
- gpio_enable_interrupt(power_button.gpio);
-}
-DECLARE_HOOK(HOOK_INIT, power_button_init, HOOK_PRIO_INIT_POWER_BUTTON);
-
-#ifdef CONFIG_POWER_BUTTON_INIT_IDLE
-/*
- * Set/clear AP_IDLE flag. It's set when the system gracefully shuts down and
- * it's cleared when the system boots up. The result is the system tries to
- * go back to the previous state upon AC plug-in. If the system uncleanly
- * shuts down, it boots immediately. If the system shuts down gracefully,
- * it'll stay at S5 and wait for power button press.
- */
-static void pb_chipset_startup(void)
-{
- chip_save_reset_flags(chip_read_reset_flags() & ~EC_RESET_FLAG_AP_IDLE);
- system_clear_reset_flags(EC_RESET_FLAG_AP_IDLE);
- CPRINTS("Cleared AP_IDLE flag");
-}
-DECLARE_HOOK(HOOK_CHIPSET_STARTUP, pb_chipset_startup, HOOK_PRIO_DEFAULT);
-
-static void pb_chipset_shutdown(void)
-{
- chip_save_reset_flags(chip_read_reset_flags() | EC_RESET_FLAG_AP_IDLE);
- system_set_reset_flags(EC_RESET_FLAG_AP_IDLE);
- CPRINTS("Saved AP_IDLE flag");
-}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pb_chipset_shutdown,
- /*
- * Slightly higher than handle_pending_reboot because
- * it may clear AP_IDLE flag.
- */
- HOOK_PRIO_DEFAULT - 1);
-#endif
-
-/**
- * Handle debounced power button changing state.
- */
-static void power_button_change_deferred(void)
-{
- const int new_pressed = raw_power_button_pressed();
-
- /* Re-enable keyboard scanning if power button is no longer pressed */
- if (!new_pressed)
- keyboard_scan_enable(1, KB_SCAN_DISABLE_POWER_BUTTON);
-
- /* If power button hasn't changed state, nothing to do */
- if (new_pressed == debounced_power_pressed) {
- power_button_is_stable = 1;
- return;
- }
-
- debounced_power_pressed = new_pressed;
- power_button_is_stable = 1;
-
- CPRINTS("%s %s",
- power_button.name, new_pressed ? "pressed" : "released");
-
- /* Call hooks */
- hook_notify(HOOK_POWER_BUTTON_CHANGE);
-
- /* Notify host if power button has been pressed */
- if (new_pressed)
- host_set_single_event(EC_HOST_EVENT_POWER_BUTTON);
-}
-DECLARE_DEFERRED(power_button_change_deferred);
-
-void power_button_interrupt(enum gpio_signal signal)
-{
- /*
- * If power button is pressed, disable the matrix scan as soon as
- * possible to reduce the risk of false-reboot triggered by those keys
- * on the same column with refresh key.
- */
- if (raw_power_button_pressed())
- keyboard_scan_enable(0, KB_SCAN_DISABLE_POWER_BUTTON);
-
- /* Reset power button debounce time */
- power_button_is_stable = 0;
- hook_call_deferred(&power_button_change_deferred_data,
- power_button.debounce_us);
-}
-
-/*****************************************************************************/
-/* Console commands */
-
-static int command_powerbtn(int argc, char **argv)
-{
- int ms = 200; /* Press duration in ms */
- char *e;
-
- if (argc > 1) {
- ms = strtoi(argv[1], &e, 0);
- if (*e)
- return EC_ERROR_PARAM1;
- }
-
- ccprintf("Simulating %d ms %s press.\n", ms, power_button.name);
- simulate_power_pressed = 1;
- power_button_is_stable = 0;
- hook_call_deferred(&power_button_change_deferred_data, 0);
-
- if (ms > 0)
- msleep(ms);
-
- ccprintf("Simulating %s release.\n", power_button.name);
- simulate_power_pressed = 0;
- power_button_is_stable = 0;
- hook_call_deferred(&power_button_change_deferred_data, 0);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(powerbtn, command_powerbtn,
- "[msec]",
- "Simulate power button press");
-
diff --git a/common/power_button_x86.c b/common/power_button_x86.c
deleted file mode 100644
index 661f9b2a3d..0000000000
--- a/common/power_button_x86.c
+++ /dev/null
@@ -1,575 +0,0 @@
-/* Copyright 2013 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.
- */
-
-/* Power button state machine for x86 platforms */
-
-#include "charge_state.h"
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "keyboard_scan.h"
-#include "lid_switch.h"
-#include "power_button.h"
-#include "switch.h"
-#include "system.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_SWITCH, outstr)
-#define CPRINTS(format, args...) cprints(CC_SWITCH, format, ## args)
-
-/*
- * x86 chipsets have a hardware timer on the power button input which causes
- * them to reset when the button is pressed for more than 4 seconds. This is
- * problematic for Chrome OS, which needs more time than that to transition
- * through the lock and logout screens. So when the system is on, we need to
- * stretch the power button signal so that the chipset will hard-reboot after 8
- * seconds instead of 4.
- *
- * When the button is pressed, we initially send a short pulse (t0); this
- * allows the chipset to process its initial power button interrupt and do
- * things like wake from suspend. We then deassert the power button signal to
- * the chipset for (t1 = 4 sec - t0), which keeps the chipset from starting its
- * hard reset timer. If the power button is still pressed after this period,
- * we again assert the power button signal for the remainder of the press
- * duration. Since (t0+t1) causes a 4-second offset, the hard reset timeout in
- * the chipset triggers after 8 seconds as desired.
- *
- * PWRBTN# --- ----
- * to EC |______________________|
- *
- *
- * PWRBTN# --- --------- ----
- * to PCH |__| |___________|
- * t0 t1 held down
- *
- * scan code | |
- * to host v v
- * @S0 make code break code
- */
-#define PWRBTN_DELAY_T0 (32 * MSEC) /* 32ms (PCH requires >16ms) */
-#define PWRBTN_DELAY_T1 (4 * SECOND - PWRBTN_DELAY_T0) /* 4 secs - t0 */
-/*
- * Length of time to stretch initial power button press to give chipset a
- * chance to wake up (~100ms) and react to the press (~16ms). Also used as
- * pulse length for simulated power button presses when the system is off.
- */
-#define PWRBTN_INITIAL_US (200 * MSEC)
-
-enum power_button_state {
- /* Button up; state machine idle */
- PWRBTN_STATE_IDLE = 0,
- /* Button pressed; debouncing done */
- PWRBTN_STATE_PRESSED,
- /* Button down, chipset on; sending initial short pulse */
- PWRBTN_STATE_T0,
- /* Button down, chipset on; delaying until we should reassert signal */
- PWRBTN_STATE_T1,
- /* Button down, signal asserted to chipset */
- PWRBTN_STATE_HELD,
- /* Force pulse due to lid-open event */
- PWRBTN_STATE_LID_OPEN,
- /* Button released; debouncing done */
- PWRBTN_STATE_RELEASED,
- /* Ignore next button release */
- PWRBTN_STATE_EAT_RELEASE,
- /*
- * Need to power on system after init, but waiting to find out if
- * sufficient battery power.
- */
- PWRBTN_STATE_INIT_ON,
- /* Forced pulse at EC boot due to keyboard controlled reset */
- PWRBTN_STATE_BOOT_KB_RESET,
- /* Power button pressed when chipset was off; stretching pulse */
- PWRBTN_STATE_WAS_OFF,
-};
-static enum power_button_state pwrbtn_state = PWRBTN_STATE_IDLE;
-
-static const char * const state_names[] = {
- "idle",
- "pressed",
- "t0",
- "t1",
- "held",
- "lid-open",
- "released",
- "eat-release",
- "init-on",
- "recovery",
- "was-off",
-};
-
-/*
- * Time for next state transition of power button state machine, or 0 if the
- * state doesn't have a timeout.
- */
-static uint64_t tnext_state;
-
-/*
- * Record the time when power button task starts. It can be used by any code
- * path that needs to compare the current time with power button task start time
- * to identify any timeouts e.g. PB state machine checks current time to
- * identify if it should wait more for charger and battery to be initialized. In
- * case of recovery using buttons (where the user could be holding the buttons
- * for >30seconds), it is not right to compare current time with the time when
- * EC was reset since the tasks would not have started. Hence, this variable is
- * being added to record the time at which power button task starts.
- */
-static uint64_t tpb_task_start;
-
-/*
- * Determines whether to execute power button pulse (t0 stage)
- */
-static int power_button_pulse_enabled = 1;
-
-static void set_pwrbtn_to_pch(int high, int init)
-{
- /*
- * If the battery is discharging and low enough we'd shut down the
- * system, don't press the power button. Also, don't press the
- * power button if the battery is charging but the battery level
- * is too low.
- */
-#ifdef CONFIG_CHARGER
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && !high &&
- (charge_want_shutdown() || charge_prevent_power_on(!init))) {
- CPRINTS("PB PCH pwrbtn ignored due to battery level");
- high = 1;
- }
-#endif
- CPRINTS("PB PCH pwrbtn=%s", high ? "HIGH" : "LOW");
- if (IS_ENABLED(CONFIG_POWER_BUTTON_TO_PCH_CUSTOM))
- board_pwrbtn_to_pch(high);
- else
- gpio_set_level(GPIO_PCH_PWRBTN_L, high);
-}
-
-void power_button_pch_press(void)
-{
- CPRINTS("PB PCH force press");
-
- /* Assert power button signal to PCH */
- if (!power_button_is_pressed())
- set_pwrbtn_to_pch(0, 0);
-}
-
-void power_button_pch_release(void)
-{
- CPRINTS("PB PCH force release");
-
- /* Deassert power button signal to PCH */
- set_pwrbtn_to_pch(1, 0);
-
- /*
- * If power button is actually pressed, eat the next release so we
- * don't send an extra release.
- */
- if (power_button_is_pressed())
- pwrbtn_state = PWRBTN_STATE_EAT_RELEASE;
- else
- pwrbtn_state = PWRBTN_STATE_IDLE;
-}
-
-void power_button_pch_pulse(void)
-{
- CPRINTS("PB PCH pulse");
-
- chipset_exit_hard_off();
- set_pwrbtn_to_pch(0, 0);
- pwrbtn_state = PWRBTN_STATE_LID_OPEN;
- tnext_state = get_time().val + PWRBTN_INITIAL_US;
- task_wake(TASK_ID_POWERBTN);
-}
-
-/**
- * Handle debounced power button down.
- */
-static void power_button_pressed(uint64_t tnow)
-{
- CPRINTS("PB pressed");
- pwrbtn_state = PWRBTN_STATE_PRESSED;
- tnext_state = tnow;
-}
-
-/**
- * Handle debounced power button up.
- */
-static void power_button_released(uint64_t tnow)
-{
- CPRINTS("PB released");
- pwrbtn_state = PWRBTN_STATE_RELEASED;
- tnext_state = tnow;
-}
-
-/**
- * Set initial power button state.
- */
-static void set_initial_pwrbtn_state(void)
-{
- uint32_t reset_flags = system_get_reset_flags();
-
- if (system_jumped_to_this_image() &&
- chipset_in_state(CHIPSET_STATE_ON)) {
- /*
- * Jumped to this image while the chipset was already on, so
- * simply reflect the actual power button state unless power
- * button pulse is disabled. If power button SMI pulse is
- * enabled, then it should be honored, else setting power
- * button to PCH could lead to x86 platform shutting down. If
- * power button is still held by the time control reaches
- * state_machine(), it would take the appropriate action there.
- */
- if (power_button_is_pressed() && power_button_pulse_enabled) {
- CPRINTS("PB init-jumped-held");
- set_pwrbtn_to_pch(0, 0);
- } else {
- CPRINTS("PB init-jumped");
- }
- return;
- } else if ((reset_flags & EC_RESET_FLAG_AP_OFF) ||
- (keyboard_scan_get_boot_keys() == BOOT_KEY_DOWN_ARROW)) {
- /* Clear AP_OFF so that it won't be carried over to RW. */
- system_clear_reset_flags(EC_RESET_FLAG_AP_OFF);
- /*
- * Reset triggered by keyboard-controlled reset, and down-arrow
- * was held down. Or reset flags request AP off.
- *
- * Leave the main processor off. This is a fail-safe
- * combination for debugging failures booting the main
- * processor.
- *
- * Don't let the PCH see that the power button was pressed.
- * Otherwise, it might power on.
- */
- CPRINTS("PB init-off");
- power_button_pch_release();
- return;
- } else if (reset_flags & EC_RESET_FLAG_AP_IDLE) {
- system_clear_reset_flags(EC_RESET_FLAG_AP_IDLE);
- pwrbtn_state = PWRBTN_STATE_IDLE;
- CPRINTS("PB idle");
- return;
- }
-
-#ifdef CONFIG_BRINGUP
- pwrbtn_state = PWRBTN_STATE_IDLE;
-#else
- pwrbtn_state = PWRBTN_STATE_INIT_ON;
-#endif
- CPRINTS("PB %s",
- pwrbtn_state == PWRBTN_STATE_INIT_ON ? "init-on" : "idle");
-}
-
-/**
- * Power button state machine.
- *
- * @param tnow Current time from usec counter
- */
-static void state_machine(uint64_t tnow)
-{
- /* Not the time to move onto next state */
- if (tnow < tnext_state)
- return;
-
- /* States last forever unless otherwise specified */
- tnext_state = 0;
-
- switch (pwrbtn_state) {
- case PWRBTN_STATE_PRESSED:
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) {
- /*
- * Chipset is off, so wake the chipset and send it a
- * long enough pulse to wake up. After that we'll
- * reflect the true power button state. If we don't
- * stretch the pulse here, the user may release the
- * power button before the chipset finishes waking from
- * hard off state.
- */
- chipset_exit_hard_off();
- tnext_state = tnow + PWRBTN_INITIAL_US;
- pwrbtn_state = PWRBTN_STATE_WAS_OFF;
- set_pwrbtn_to_pch(0, 0);
- } else {
- if (power_button_pulse_enabled) {
- /* Chipset is on, so send the chipset a pulse */
- tnext_state = tnow + PWRBTN_DELAY_T0;
- pwrbtn_state = PWRBTN_STATE_T0;
- set_pwrbtn_to_pch(0, 0);
- } else {
- tnext_state = tnow + PWRBTN_DELAY_T1;
- pwrbtn_state = PWRBTN_STATE_T1;
- }
- }
- break;
- case PWRBTN_STATE_T0:
- tnext_state = tnow + PWRBTN_DELAY_T1;
- pwrbtn_state = PWRBTN_STATE_T1;
- set_pwrbtn_to_pch(1, 0);
- break;
- case PWRBTN_STATE_T1:
- /*
- * If the chipset is already off, don't tell it the power
- * button is down; it'll just cause the chipset to turn on
- * again.
- */
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
- CPRINTS("PB chipset already off");
- else
- set_pwrbtn_to_pch(0, 0);
- pwrbtn_state = PWRBTN_STATE_HELD;
- break;
- case PWRBTN_STATE_RELEASED:
- case PWRBTN_STATE_LID_OPEN:
- set_pwrbtn_to_pch(1, 0);
- pwrbtn_state = PWRBTN_STATE_IDLE;
- break;
- case PWRBTN_STATE_INIT_ON:
-
- /*
- * Before attempting to power the system on, we need to allow
- * time for charger, battery and USB-C PD initialization to be
- * ready to supply sufficient power. Check every 100
- * milliseconds, and give up CONFIG_POWER_BUTTON_INIT_TIMEOUT
- * seconds after the PB task was started. Here, it is
- * important to check the current time against PB task start
- * time to prevent unnecessary timeouts happening in recovery
- * case where the tasks could start as late as 30 seconds
- * after EC reset.
- */
-
- if (!IS_ENABLED(CONFIG_CHARGER) || charge_prevent_power_on(0)) {
- if (tnow >
- (tpb_task_start +
- CONFIG_POWER_BUTTON_INIT_TIMEOUT * SECOND)) {
- pwrbtn_state = PWRBTN_STATE_IDLE;
- break;
- }
-
- if (IS_ENABLED(CONFIG_CHARGER)) {
- tnext_state = tnow + 100 * MSEC;
- break;
- }
- }
-
- /*
- * Power the system on if possible. Gating due to insufficient
- * battery is handled inside set_pwrbtn_to_pch().
- */
- chipset_exit_hard_off();
-#ifdef CONFIG_DELAY_DSW_PWROK_TO_PWRBTN
- /* Check if power button is ready. If not, we'll come back. */
- if (get_time().val - get_time_dsw_pwrok() <
- CONFIG_DSW_PWROK_TO_PWRBTN_US) {
- tnext_state = get_time_dsw_pwrok() +
- CONFIG_DSW_PWROK_TO_PWRBTN_US;
- break;
- }
-#endif
-
- set_pwrbtn_to_pch(0, 1);
- tnext_state = get_time().val + PWRBTN_INITIAL_US;
- pwrbtn_state = PWRBTN_STATE_BOOT_KB_RESET;
- break;
-
- case PWRBTN_STATE_BOOT_KB_RESET:
- /* Initial forced pulse is done. Ignore the actual power
- * button until it's released, so that holding down the
- * recovery combination doesn't cause the chipset to shut back
- * down. */
- set_pwrbtn_to_pch(1, 0);
- if (power_button_is_pressed())
- pwrbtn_state = PWRBTN_STATE_EAT_RELEASE;
- else
- pwrbtn_state = PWRBTN_STATE_IDLE;
- break;
- case PWRBTN_STATE_WAS_OFF:
- /* Done stretching initial power button signal, so show the
- * true power button state to the PCH. */
- if (power_button_is_pressed()) {
- /* User is still holding the power button */
- pwrbtn_state = PWRBTN_STATE_HELD;
- } else {
- /* Stop stretching the power button press */
- power_button_released(tnow);
- }
- break;
- case PWRBTN_STATE_IDLE:
- case PWRBTN_STATE_HELD:
- case PWRBTN_STATE_EAT_RELEASE:
- /* Do nothing */
- break;
- }
-}
-
-void power_button_task(void *u)
-{
- uint64_t t;
- uint64_t tsleep;
-
- /*
- * Record the time when the task starts so that the state machine can
- * use this to identify any timeouts.
- */
- tpb_task_start = get_time().val;
-
- while (1) {
- t = get_time().val;
-
- /* Update state machine */
- CPRINTS("PB task %d = %s", pwrbtn_state,
- state_names[pwrbtn_state]);
-
- state_machine(t);
-
- /* Sleep until our next timeout */
- tsleep = -1;
- if (tnext_state && tnext_state < tsleep)
- tsleep = tnext_state;
- t = get_time().val;
- if (tsleep > t) {
- unsigned d = tsleep == -1 ? -1 : (unsigned)(tsleep - t);
- /*
- * (Yes, the conversion from uint64_t to unsigned could
- * theoretically overflow if we wanted to sleep for
- * more than 2^32 us, but our timeouts are small enough
- * that can't happen - and even if it did, we'd just go
- * back to sleep after deciding that we woke up too
- * early.)
- */
- CPRINTS("PB task %d = %s, wait %d", pwrbtn_state,
- state_names[pwrbtn_state], d);
- task_wait_event(d);
- }
- }
-}
-
-/*****************************************************************************/
-/* Hooks */
-
-static void powerbtn_x86_init(void)
-{
- set_initial_pwrbtn_state();
-}
-DECLARE_HOOK(HOOK_INIT, powerbtn_x86_init, HOOK_PRIO_DEFAULT);
-
-#ifdef CONFIG_LID_SWITCH
-/**
- * Handle switch changes based on lid event.
- */
-static void powerbtn_x86_lid_change(void)
-{
- /* If chipset is off, pulse the power button on lid open to wake it. */
- if (lid_is_open() && chipset_in_state(CHIPSET_STATE_ANY_OFF)
- && pwrbtn_state != PWRBTN_STATE_INIT_ON)
- power_button_pch_pulse();
-}
-DECLARE_HOOK(HOOK_LID_CHANGE, powerbtn_x86_lid_change, HOOK_PRIO_DEFAULT);
-#endif
-
-/**
- * Handle debounced power button changing state.
- */
-static void powerbtn_x86_changed(void)
-{
- if (pwrbtn_state == PWRBTN_STATE_BOOT_KB_RESET ||
- pwrbtn_state == PWRBTN_STATE_INIT_ON ||
- pwrbtn_state == PWRBTN_STATE_LID_OPEN ||
- pwrbtn_state == PWRBTN_STATE_WAS_OFF) {
- /* Ignore all power button changes during an initial pulse */
- CPRINTS("PB ignoring change");
- return;
- }
-
- if (power_button_is_pressed()) {
- /* Power button pressed */
- power_button_pressed(get_time().val);
- } else {
- /* Power button released */
- if (pwrbtn_state == PWRBTN_STATE_EAT_RELEASE) {
- /*
- * Ignore the first power button release if we already
- * told the PCH the power button was released.
- */
- CPRINTS("PB ignoring release");
- pwrbtn_state = PWRBTN_STATE_IDLE;
- return;
- }
-
- power_button_released(get_time().val);
- }
-
- /* Wake the power button task */
- task_wake(TASK_ID_POWERBTN);
-}
-DECLARE_HOOK(HOOK_POWER_BUTTON_CHANGE, powerbtn_x86_changed, HOOK_PRIO_DEFAULT);
-
-/**
- * Handle configuring the power button behavior through a host command
- */
-static enum ec_status hc_config_powerbtn_x86(struct host_cmd_handler_args *args)
-{
- const struct ec_params_config_power_button *p = args->params;
-
- power_button_pulse_enabled =
- !!(p->flags & EC_POWER_BUTTON_ENABLE_PULSE);
-
- return EC_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_CONFIG_POWER_BUTTON, hc_config_powerbtn_x86,
- EC_VER_MASK(0));
-
-
-/*
- * Currently, the only reason why we disable power button pulse is to allow
- * detachable menu on AP to use power button for selection purpose without
- * triggering SMI. Thus, re-enable the pulse any time there is a chipset
- * state transition event.
- */
-static void power_button_pulse_setting_reset(void)
-{
- power_button_pulse_enabled = 1;
-}
-
-DECLARE_HOOK(HOOK_CHIPSET_STARTUP, power_button_pulse_setting_reset,
- HOOK_PRIO_DEFAULT);
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, power_button_pulse_setting_reset,
- HOOK_PRIO_DEFAULT);
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, power_button_pulse_setting_reset,
- HOOK_PRIO_DEFAULT);
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, power_button_pulse_setting_reset,
- HOOK_PRIO_DEFAULT);
-
-#define POWER_BUTTON_SYSJUMP_TAG 0x5042 /* PB */
-#define POWER_BUTTON_HOOK_VERSION 1
-
-static void power_button_pulse_setting_restore_state(void)
-{
- const int *state;
- int version, size;
-
- state = (const int *)system_get_jump_tag(POWER_BUTTON_SYSJUMP_TAG,
- &version, &size);
-
- if (state && (version == POWER_BUTTON_HOOK_VERSION) &&
- (size == sizeof(power_button_pulse_enabled)))
- power_button_pulse_enabled = *state;
-}
-DECLARE_HOOK(HOOK_INIT, power_button_pulse_setting_restore_state,
- HOOK_PRIO_INIT_POWER_BUTTON + 1);
-
-static void power_button_pulse_setting_preserve_state(void)
-{
- system_add_jump_tag(POWER_BUTTON_SYSJUMP_TAG,
- POWER_BUTTON_HOOK_VERSION,
- sizeof(power_button_pulse_enabled),
- &power_button_pulse_enabled);
-}
-DECLARE_HOOK(HOOK_SYSJUMP, power_button_pulse_setting_preserve_state,
- HOOK_PRIO_DEFAULT);
diff --git a/common/pstore_commands.c b/common/pstore_commands.c
deleted file mode 100644
index 52270cd1cf..0000000000
--- a/common/pstore_commands.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* Copyright 2012 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.
- */
-
-/* Persistent storage commands for Chrome EC */
-
-#include "common.h"
-#include "eeprom.h"
-#include "host_command.h"
-#include "util.h"
-
-enum ec_status pstore_command_get_info(struct host_cmd_handler_args *args)
-{
- struct ec_response_pstore_info *r = args->response;
-
- ASSERT(EEPROM_BLOCK_START_PSTORE + EEPROM_BLOCK_COUNT_PSTORE <=
- eeprom_get_block_count());
-
- r->pstore_size = EEPROM_BLOCK_COUNT_PSTORE * eeprom_get_block_size();
- r->access_size = sizeof(uint32_t);
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PSTORE_INFO,
- pstore_command_get_info,
- EC_VER_MASK(0));
-
-enum ec_status pstore_command_read(struct host_cmd_handler_args *args)
-{
- const struct ec_params_pstore_read *p = args->params;
- char *dest = args->response;
- int block_size = eeprom_get_block_size();
- int block = p->offset / block_size + EEPROM_BLOCK_START_PSTORE;
- int offset = p->offset % block_size;
- int bytes_left = p->size;
-
- if (p->size > args->response_max)
- return EC_RES_INVALID_PARAM;
-
- while (bytes_left) {
- /* Read what we can from the current block */
- int bytes_this = MIN(bytes_left, block_size - offset);
-
- if (block >=
- EEPROM_BLOCK_START_PSTORE + EEPROM_BLOCK_COUNT_PSTORE)
- return EC_RES_ERROR;
-
- if (eeprom_read(block, offset, bytes_this, dest))
- return EC_RES_ERROR;
-
- /* Continue to the next block if necessary */
- offset = 0;
- block++;
- bytes_left -= bytes_this;
- dest += bytes_this;
- }
-
- args->response_size = p->size;
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PSTORE_READ,
- pstore_command_read,
- EC_VER_MASK(0));
-
-enum ec_status pstore_command_write(struct host_cmd_handler_args *args)
-{
- const struct ec_params_pstore_write *p = args->params;
-
- const char *src = p->data;
- int block_size = eeprom_get_block_size();
- int block = p->offset / block_size + EEPROM_BLOCK_START_PSTORE;
- int offset = p->offset % block_size;
- int bytes_left = p->size;
-
- if (p->size > sizeof(p->data))
- return EC_RES_ERROR;
-
- while (bytes_left) {
- /* Write what we can to the current block */
- int bytes_this = MIN(bytes_left, block_size - offset);
-
- if (block >=
- EEPROM_BLOCK_START_PSTORE + EEPROM_BLOCK_COUNT_PSTORE)
- return EC_RES_ERROR;
-
- if (eeprom_write(block, offset, bytes_this, src))
- return EC_RES_ERROR;
-
- /* Continue to the next block if necessary */
- offset = 0;
- block++;
- bytes_left -= bytes_this;
- src += bytes_this;
- }
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PSTORE_WRITE,
- pstore_command_write,
- EC_VER_MASK(0));
diff --git a/common/pwm.c b/common/pwm.c
deleted file mode 100644
index 41989a94e0..0000000000
--- a/common/pwm.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/* Copyright 2013 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.
- */
-
-#include "common.h"
-#include "console.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "pwm.h"
-#include "util.h"
-
-#ifdef CONFIG_ZEPHYR
-#include "pwm/pwm.h"
-#endif
-
-#ifdef CONFIG_PWM
-
-/*
- * Get target channel based on type / index host command parameters.
- * Returns 0 if a valid channel is selected, -1 on error.
- */
-static int get_target_channel(enum pwm_channel *channel, int type, int index)
-{
- switch (type) {
- case EC_PWM_TYPE_GENERIC:
- *channel = index;
- break;
-#ifdef CONFIG_PWM_KBLIGHT
- case EC_PWM_TYPE_KB_LIGHT:
- *channel = PWM_CH_KBLIGHT;
- break;
-#endif
-#ifdef CONFIG_PWM_DISPLIGHT
- case EC_PWM_TYPE_DISPLAY_LIGHT:
- *channel = PWM_CH_DISPLIGHT;
- break;
-#endif
- default:
- return -1;
- }
-
- return *channel >= PWM_CH_COUNT;
-}
-
-__attribute__((weak)) void pwm_set_raw_duty(enum pwm_channel ch, uint16_t duty)
-{
- int percent;
-
- /* Convert 16 bit duty to percent on [0, 100] */
- percent = DIV_ROUND_NEAREST((uint32_t)duty * 100, 65535);
- pwm_set_duty(ch, percent);
-}
-
-__attribute__((weak)) uint16_t pwm_get_raw_duty(enum pwm_channel ch)
-{
- return (pwm_get_duty(ch) * 65535) / 100;
-}
-
-static enum ec_status
-host_command_pwm_set_duty(struct host_cmd_handler_args *args)
-{
- const struct ec_params_pwm_set_duty *p = args->params;
- enum pwm_channel channel;
-
- if (get_target_channel(&channel, p->pwm_type, p->index))
- return EC_RES_INVALID_PARAM;
-
- pwm_set_raw_duty(channel, p->duty);
- pwm_enable(channel, p->duty > 0);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_DUTY,
- host_command_pwm_set_duty,
- EC_VER_MASK(0));
-
-static enum ec_status
-host_command_pwm_get_duty(struct host_cmd_handler_args *args)
-{
- const struct ec_params_pwm_get_duty *p = args->params;
- struct ec_response_pwm_get_duty *r = args->response;
-
- enum pwm_channel channel;
-
- if (get_target_channel(&channel, p->pwm_type, p->index))
- return EC_RES_INVALID_PARAM;
-
- r->duty = pwm_get_raw_duty(channel);
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_DUTY,
- host_command_pwm_get_duty,
- EC_VER_MASK(0));
-
-/**
- * Print status of a PWM channel.
- *
- * @param ch Channel to print.
- */
-static void print_channel(enum pwm_channel ch, int max_duty)
-{
- if (pwm_get_enabled(ch))
- if (max_duty == 100)
- ccprintf(" %d: %d%%\n", ch, pwm_get_duty(ch));
- else
- ccprintf(" %d: %d\n", ch, pwm_get_raw_duty(ch));
- else
- ccprintf(" %d: disabled\n", ch);
-}
-
-static int cc_pwm_duty(int argc, char **argv)
-{
- int value = 0;
- int max_duty = 100;
- int ch;
- char *e;
- char *raw;
-
- if (argc < 2) {
- ccprintf("PWM channels:\n");
- for (ch = 0; ch < PWM_CH_COUNT; ch++)
- print_channel(ch, max_duty);
- return EC_SUCCESS;
- }
-
- ch = strtoi(argv[1], &e, 0);
- if (*e || ch < 0 || ch >= PWM_CH_COUNT)
- return EC_ERROR_PARAM1;
-
- if (argc > 2) {
- raw = argv[2];
- if (!strcasecmp(raw, "raw")) {
- /* use raw duty */
- value = strtoi(argv[3], &e, 0);
- max_duty = EC_PWM_MAX_DUTY;
- } else {
- /* use percent duty */
- value = strtoi(argv[2], &e, 0);
- max_duty = 100;
- }
-
- if (*e || value > max_duty) {
- /* Bad param */
- return EC_ERROR_PARAM2;
- } else if (value < 0) {
- /* Negative = disable */
- pwm_enable(ch, 0);
- } else {
- ccprintf("Setting channel %d to %d\n", ch, value);
- pwm_enable(ch, 1);
- (max_duty == 100) ? pwm_set_duty(ch, value) :
- pwm_set_raw_duty(ch, value);
- }
- }
-
- print_channel(ch, max_duty);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(pwmduty, cc_pwm_duty,
- "[channel [<percent> | -1=disable] | [raw <value>]]",
- "Get/set PWM duty cycles ");
-#endif /* CONFIG_PWM */
-
-#ifndef CONFIG_ZEPHYR
-/*
- * Initialize all PWM pins as functional. This is not required under
- * Zephyr as pin configuration is automatically performed by chip driver
- */
-static void pwm_pin_init(void)
-{
- gpio_config_module(MODULE_PWM, 1);
-}
-/* HOOK_PRIO_INIT_PWM may be used for chip PWM unit init, so use PRIO + 1 */
-DECLARE_HOOK(HOOK_INIT, pwm_pin_init, HOOK_PRIO_INIT_PWM + 1);
-#endif /* CONFIG_ZEPHYR */
diff --git a/common/pwm_kblight.c b/common/pwm_kblight.c
deleted file mode 100644
index 4967d36df5..0000000000
--- a/common/pwm_kblight.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Copyright 2013 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.
- */
-
-/* PWM control module for keyboard backlight. */
-
-#include "common.h"
-#include "keyboard_backlight.h"
-#include "pwm.h"
-#include "system.h"
-#include "util.h"
-
-const enum pwm_channel kblight_pwm_ch = PWM_CH_KBLIGHT;
-
-static int kblight_pwm_set(int percent)
-{
- pwm_set_duty(kblight_pwm_ch, percent);
- return EC_SUCCESS;
-}
-
-static int kblight_pwm_get(void)
-{
- return pwm_get_duty(kblight_pwm_ch);
-}
-
-static int kblight_pwm_init(void)
-{
- /* dnojiri: Why do we need save/restore setting over sysjump? */
- kblight_pwm_set(0);
- pwm_enable(kblight_pwm_ch, 0);
- return EC_SUCCESS;
-}
-
-static int kblight_pwm_enable(int enable)
-{
- pwm_enable(kblight_pwm_ch, enable);
- return EC_SUCCESS;
-}
-
-const struct kblight_drv kblight_pwm = {
- .init = kblight_pwm_init,
- .set = kblight_pwm_set,
- .get = kblight_pwm_get,
- .enable = kblight_pwm_enable,
-};
diff --git a/common/regulator.c b/common/regulator.c
deleted file mode 100644
index c3f5d0b99d..0000000000
--- a/common/regulator.c
+++ /dev/null
@@ -1,99 +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.
- */
-
-/* Regulator control module for Chrome EC */
-
-#include "common.h"
-#include "console.h"
-#include "ec_commands.h"
-#include "host_command.h"
-#include "regulator.h"
-
-static enum ec_status
-hc_regulator_get_info(struct host_cmd_handler_args *args)
-{
- const struct ec_params_regulator_get_info *p = args->params;
- struct ec_response_regulator_get_info *r = args->response;
- int rv;
-
- rv = board_regulator_get_info(p->index, r->name, &r->num_voltages,
- r->voltages_mv);
-
- if (rv)
- return EC_RES_ERROR;
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_REGULATOR_GET_INFO, hc_regulator_get_info,
- EC_VER_MASK(0));
-
-static enum ec_status
-hc_regulator_enable(struct host_cmd_handler_args *args)
-{
- const struct ec_params_regulator_enable *p = args->params;
- int rv;
-
- rv = board_regulator_enable(p->index, p->enable);
-
- if (rv)
- return EC_RES_ERROR;
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_REGULATOR_ENABLE, hc_regulator_enable,
- EC_VER_MASK(0));
-
-static enum ec_status
-hc_regulator_is_enabled(struct host_cmd_handler_args *args)
-{
- const struct ec_params_regulator_is_enabled *p = args->params;
- struct ec_response_regulator_is_enabled *r = args->response;
- int rv;
-
- rv = board_regulator_is_enabled(p->index, &r->enabled);
-
- if (rv)
- return EC_RES_ERROR;
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_REGULATOR_IS_ENABLED, hc_regulator_is_enabled,
- EC_VER_MASK(0));
-
-static enum ec_status
-hc_regulator_get_voltage(struct host_cmd_handler_args *args)
-{
- const struct ec_params_regulator_get_voltage *p = args->params;
- struct ec_response_regulator_get_voltage *r = args->response;
- int rv;
-
- rv = board_regulator_get_voltage(p->index, &r->voltage_mv);
-
- if (rv)
- return EC_RES_ERROR;
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_REGULATOR_GET_VOLTAGE, hc_regulator_get_voltage,
- EC_VER_MASK(0));
-
-static enum ec_status
-hc_regulator_set_voltage(struct host_cmd_handler_args *args)
-{
- const struct ec_params_regulator_set_voltage *p = args->params;
- int rv;
-
- rv = board_regulator_set_voltage(p->index, p->min_mv, p->max_mv);
-
- if (rv)
- return EC_RES_ERROR;
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_REGULATOR_SET_VOLTAGE, hc_regulator_set_voltage,
- EC_VER_MASK(0));
diff --git a/common/rollback.c b/common/rollback.c
deleted file mode 100644
index 984058c49a..0000000000
--- a/common/rollback.c
+++ /dev/null
@@ -1,520 +0,0 @@
-/* Copyright 2017 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.
- */
-
-/* Rollback protection logic. */
-
-#include "common.h"
-#include "console.h"
-#ifdef CONFIG_LIBCRYPTOC
-#include "cryptoc/util.h"
-#endif
-#include "flash.h"
-#include "hooks.h"
-#include "host_command.h"
-#ifdef CONFIG_MPU
-#include "mpu.h"
-#endif
-#include "rollback.h"
-#include "rollback_private.h"
-#include "sha256.h"
-#include "system.h"
-#include "task.h"
-#include "trng.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args)
-
-/* Number of rollback regions */
-#define ROLLBACK_REGIONS 2
-
-static int get_rollback_offset(int region)
-{
-#ifdef CONFIG_FLASH_MULTIPLE_REGION
- int rv;
- int rollback_start_bank = crec_flash_bank_index(CONFIG_ROLLBACK_OFF);
-
- rv = crec_flash_bank_start_offset(rollback_start_bank + region);
- ASSERT(rv >= 0);
- return rv;
-#else
- return CONFIG_ROLLBACK_OFF + region * CONFIG_FLASH_ERASE_SIZE;
-#endif
-}
-
-#ifdef SECTION_IS_RO
-static int get_rollback_erase_size_bytes(int region)
-{
- int erase_size;
-
-#ifndef CONFIG_FLASH_MULTIPLE_REGION
- erase_size = CONFIG_FLASH_ERASE_SIZE;
-#else
- int rollback_start_bank = crec_flash_bank_index(CONFIG_ROLLBACK_OFF);
-
- erase_size = crec_flash_bank_erase_size(rollback_start_bank + region);
-#endif
- ASSERT(erase_size > 0);
- ASSERT(ROLLBACK_REGIONS * erase_size <= CONFIG_ROLLBACK_SIZE);
- ASSERT(sizeof(struct rollback_data) <= erase_size);
- return erase_size;
-}
-#endif
-
-/*
- * When MPU is available, read rollback with interrupts disabled, to minimize
- * time protection is left open.
- */
-static void lock_rollback(void)
-{
-#ifdef CONFIG_ROLLBACK_MPU_PROTECT
- mpu_lock_rollback(1);
- interrupt_enable();
-#endif
-}
-
-static void unlock_rollback(void)
-{
-#ifdef CONFIG_ROLLBACK_MPU_PROTECT
- interrupt_disable();
- mpu_lock_rollback(0);
-#endif
-}
-
-static void clear_rollback(struct rollback_data *data)
-{
-#ifdef CONFIG_ROLLBACK_SECRET_SIZE
- always_memset(data->secret, 0, sizeof(data->secret));
-#endif
-}
-
-int read_rollback(int region, struct rollback_data *data)
-{
- int offset;
- int ret = EC_SUCCESS;
-
- offset = get_rollback_offset(region);
-
- unlock_rollback();
- if (crec_flash_read(offset, sizeof(*data), (char *)data))
- ret = EC_ERROR_UNKNOWN;
- lock_rollback();
-
- return ret;
-}
-
-/*
- * Get the most recent rollback information.
- *
- * @data: Returns most recent rollback data block. The data is filled
- * with zeros if no valid rollback block is present
- *
- * Return most recent region index on success (>= 0, or 0 if no rollback
- * region is valid), negative value on error.
- */
-static int get_latest_rollback(struct rollback_data *data)
-{
- int ret = -1;
- int region;
- int min_region = -1;
- int max_id = -1;
- struct rollback_data tmp_data;
-
- for (region = 0; region < ROLLBACK_REGIONS; region++) {
- if (read_rollback(region, &tmp_data))
- goto failed;
-
- /* Check if not initialized or invalid cookie. */
- if (tmp_data.cookie != CROS_EC_ROLLBACK_COOKIE)
- continue;
-
- if (tmp_data.id > max_id) {
- min_region = region;
- max_id = tmp_data.id;
- }
- }
-
- if (min_region >= 0) {
- if (read_rollback(min_region, data))
- goto failed;
- } else {
- min_region = 0;
- clear_rollback(data);
- }
- ret = min_region;
-
-failed:
- clear_rollback(&tmp_data);
- return ret;
-}
-
-int32_t rollback_get_minimum_version(void)
-{
- struct rollback_data data;
- int32_t ret = -1;
-
- if (get_latest_rollback(&data) < 0)
- goto failed;
- ret = data.rollback_min_version;
-
-failed:
- clear_rollback(&data);
- return ret;
-}
-
-#ifdef CONFIG_ROLLBACK_SECRET_SIZE
-test_mockable int rollback_get_secret(uint8_t *secret)
-{
- int ret = EC_ERROR_UNKNOWN;
- struct rollback_data data;
-
- if (get_latest_rollback(&data) < 0)
- goto failed;
-
- /* Check that secret is not full of 0x00 or 0xff */
- if (bytes_are_trivial(data.secret, sizeof(data.secret)))
- goto failed;
-
- memcpy(secret, data.secret, sizeof(data.secret));
- ret = EC_SUCCESS;
-failed:
- clear_rollback(&data);
- return ret;
-}
-#endif
-
-#ifdef CONFIG_ROLLBACK_UPDATE
-
-#ifdef CONFIG_ROLLBACK_SECRET_SIZE
-static int add_entropy(uint8_t *dst, const uint8_t *src,
- const uint8_t *add, unsigned int add_len)
-{
- int ret = 0;
-#ifdef CONFIG_SHA256
-BUILD_ASSERT(SHA256_DIGEST_SIZE == CONFIG_ROLLBACK_SECRET_SIZE);
- struct sha256_ctx ctx;
- uint8_t *hash;
-#ifdef CONFIG_ROLLBACK_SECRET_LOCAL_ENTROPY_SIZE
- uint8_t extra;
- int i;
-#endif
-
- SHA256_init(&ctx);
- SHA256_update(&ctx, src, CONFIG_ROLLBACK_SECRET_SIZE);
- SHA256_update(&ctx, add, add_len);
-#ifdef CONFIG_ROLLBACK_SECRET_LOCAL_ENTROPY_SIZE
- /* Add some locally produced entropy */
- for (i = 0; i < CONFIG_ROLLBACK_SECRET_LOCAL_ENTROPY_SIZE; i++) {
- if (!board_get_entropy(&extra, 1))
- goto failed;
- SHA256_update(&ctx, &extra, 1);
- }
-#endif
- hash = SHA256_final(&ctx);
-
- memcpy(dst, hash, CONFIG_ROLLBACK_SECRET_SIZE);
- ret = 1;
-
-#ifdef CONFIG_ROLLBACK_SECRET_LOCAL_ENTROPY_SIZE
-failed:
-#endif
- always_memset(&ctx, 0, sizeof(ctx));
-#else
-#error "Adding entropy to secret in rollback region requires SHA256."
-#endif
- return ret;
-}
-#endif /* CONFIG_ROLLBACK_SECRET_SIZE */
-
-/**
- * Update rollback block.
- *
- * @param next_min_version Minimum version to update in rollback block. Can
- * be a negative value if entropy is provided (in
- * that case the current minimum version is kept).
- * @param entropy Entropy to be added to rollback block secret
- * (can be NULL, in that case no entropy is added).
- * @param len entropy length
- *
- * @return EC_SUCCESS on success, EC_ERROR_* on error.
- */
-static int rollback_update(int32_t next_min_version,
- const uint8_t *entropy, unsigned int length)
-{
- /*
- * When doing flash_write operation, the data needs to be in blocks
- * of CONFIG_FLASH_WRITE_SIZE, pad rollback_data as required.
- */
- uint8_t block[CONFIG_FLASH_WRITE_SIZE *
- DIV_ROUND_UP(sizeof(struct rollback_data),
- CONFIG_FLASH_WRITE_SIZE)];
- struct rollback_data *data = (struct rollback_data *)block;
- BUILD_ASSERT(sizeof(block) >= sizeof(*data));
- int erase_size, offset, region, ret;
-
- if (crec_flash_get_protect() & EC_FLASH_PROTECT_ROLLBACK_NOW) {
- ret = EC_ERROR_ACCESS_DENIED;
- goto out;
- }
-
- /* Initialize the rest of the block. */
- memset(&block[sizeof(*data)], 0xff, sizeof(block)-sizeof(*data));
-
- region = get_latest_rollback(data);
-
- if (region < 0) {
- ret = EC_ERROR_UNKNOWN;
- goto out;
- }
-
-#ifdef CONFIG_ROLLBACK_SECRET_SIZE
- if (entropy) {
- /* Do not accept to decrease the value. */
- if (next_min_version < data->rollback_min_version)
- next_min_version = data->rollback_min_version;
- } else
-#endif
- {
- /* Do not accept to decrease the value. */
- if (next_min_version < data->rollback_min_version) {
- ret = EC_ERROR_INVAL;
- goto out;
- }
-
- /* No need to update if version is already correct. */
- if (next_min_version == data->rollback_min_version) {
- ret = EC_SUCCESS;
- goto out;
- }
- }
-
- /* Use the other region. */
- region = (region + 1) % ROLLBACK_REGIONS;
-
- offset = get_rollback_offset(region);
-
- data->id = data->id + 1;
- data->rollback_min_version = next_min_version;
-#ifdef CONFIG_ROLLBACK_SECRET_SIZE
- /*
- * If we are provided with some entropy, add it to secret. Otherwise,
- * data.secret is left untouched and written back to the other region.
- */
- if (entropy) {
- if (!add_entropy(data->secret, data->secret, entropy, length)) {
- ret = EC_ERROR_UNCHANGED;
- goto out;
- }
- }
-#endif
- data->cookie = CROS_EC_ROLLBACK_COOKIE;
-
- erase_size = get_rollback_erase_size_bytes(region);
-
- if (erase_size < 0) {
- ret = EC_ERROR_UNKNOWN;
- goto out;
- }
-
- /* Offset should never be part of active image. */
- if (system_unsafe_to_overwrite(offset, erase_size)) {
- ret = EC_ERROR_UNKNOWN;
- goto out;
- }
-
- unlock_rollback();
- if (crec_flash_erase(offset, erase_size)) {
- ret = EC_ERROR_UNKNOWN;
- lock_rollback();
- goto out;
- }
-
- ret = crec_flash_write(offset, sizeof(block), block);
- lock_rollback();
-
-out:
- clear_rollback(data);
- return ret;
-}
-
-int rollback_update_version(int32_t next_min_version)
-{
- return rollback_update(next_min_version, NULL, 0);
-}
-
-int rollback_add_entropy(const uint8_t *data, unsigned int len)
-{
- return rollback_update(-1, data, len);
-}
-
-static int command_rollback_update(int argc, char **argv)
-{
- int32_t min_version;
- char *e;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- min_version = strtoi(argv[1], &e, 0);
-
- if (*e || min_version < 0)
- return EC_ERROR_PARAM1;
-
- return rollback_update_version(min_version);
-}
-DECLARE_CONSOLE_COMMAND(rollbackupdate, command_rollback_update,
- "min_version",
- "Update rollback info");
-
-#ifdef CONFIG_ROLLBACK_SECRET_SIZE
-static int command_rollback_add_entropy(int argc, char **argv)
-{
- int len;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- len = strlen(argv[1]);
-
- return rollback_add_entropy(argv[1], len);
-}
-DECLARE_CONSOLE_COMMAND(rollbackaddent, command_rollback_add_entropy,
- "data",
- "Add entropy to rollback block");
-
-#ifdef CONFIG_RNG
-static int add_entropy_action;
-static int add_entropy_rv = EC_RES_UNAVAILABLE;
-
-static void add_entropy_deferred(void)
-{
- uint8_t rand[CONFIG_ROLLBACK_SECRET_SIZE];
- int repeat = 1;
-
- /*
- * If asked to reset the old secret, just add entropy multiple times,
- * which will ping-pong between the blocks.
- */
- if (add_entropy_action == ADD_ENTROPY_RESET_ASYNC)
- repeat = ROLLBACK_REGIONS;
-
- init_trng();
- do {
- rand_bytes(rand, sizeof(rand));
- if (rollback_add_entropy(rand, sizeof(rand)) != EC_SUCCESS) {
- add_entropy_rv = EC_RES_ERROR;
- goto out;
- }
- } while (--repeat);
-
- add_entropy_rv = EC_RES_SUCCESS;
-out:
- exit_trng();
-}
-DECLARE_DEFERRED(add_entropy_deferred);
-
-static enum ec_status
-hc_rollback_add_entropy(struct host_cmd_handler_args *args)
-{
- const struct ec_params_rollback_add_entropy *p = args->params;
-
- switch (p->action) {
- case ADD_ENTROPY_ASYNC:
- case ADD_ENTROPY_RESET_ASYNC:
- if (add_entropy_rv == EC_RES_BUSY)
- return EC_RES_BUSY;
-
- add_entropy_action = p->action;
- add_entropy_rv = EC_RES_BUSY;
- hook_call_deferred(&add_entropy_deferred_data, 0);
-
- return EC_RES_SUCCESS;
-
- case ADD_ENTROPY_GET_RESULT:
- return add_entropy_rv;
- }
-
- return EC_RES_INVALID_PARAM;
-}
-DECLARE_HOST_COMMAND(EC_CMD_ADD_ENTROPY,
- hc_rollback_add_entropy,
- EC_VER_MASK(0));
-#endif /* CONFIG_RNG */
-#endif /* CONFIG_ROLLBACK_SECRET_SIZE */
-#endif /* CONFIG_ROLLBACK_UPDATE */
-
-static int command_rollback_info(int argc, char **argv)
-{
- int ret = EC_ERROR_UNKNOWN;
- int region, min_region;
- int32_t rw_rollback_version;
- struct rollback_data data;
-
- min_region = get_latest_rollback(&data);
-
- if (min_region < 0)
- goto failed;
-
- rw_rollback_version = system_get_rollback_version(EC_IMAGE_RW);
-
- ccprintf("rollback minimum version: %d\n", data.rollback_min_version);
- ccprintf("RW rollback version: %d\n", rw_rollback_version);
-
- for (region = 0; region < ROLLBACK_REGIONS; region++) {
- ret = read_rollback(region, &data);
- if (ret)
- goto failed;
-
- ccprintf("rollback %d: %08x %08x %08x",
- region, data.id, data.rollback_min_version,
- data.cookie);
-#ifdef CONFIG_ROLLBACK_SECRET_SIZE
- if (!system_is_locked()) {
- /* If system is unlocked, show some of the secret. */
- ccprintf(" [%02x..%02x]", data.secret[0],
- data.secret[CONFIG_ROLLBACK_SECRET_SIZE-1]);
- }
-#endif
- if (min_region == region)
- ccprintf(" *");
- ccprintf("\n");
- }
- ret = EC_SUCCESS;
-
-failed:
- clear_rollback(&data);
- return ret;
-}
-DECLARE_SAFE_CONSOLE_COMMAND(rollbackinfo, command_rollback_info,
- NULL,
- "Print rollback info");
-
-static enum ec_status
-host_command_rollback_info(struct host_cmd_handler_args *args)
-{
- int ret = EC_RES_UNAVAILABLE;
- struct ec_response_rollback_info *r = args->response;
- int min_region;
- struct rollback_data data;
-
- min_region = get_latest_rollback(&data);
-
- if (min_region < 0)
- goto failed;
-
- r->id = data.id;
- r->rollback_min_version = data.rollback_min_version;
- r->rw_rollback_version = system_get_rollback_version(EC_IMAGE_RW);
-
- args->response_size = sizeof(*r);
- ret = EC_RES_SUCCESS;
-
-failed:
- clear_rollback(&data);
- return ret;
-}
-DECLARE_HOST_COMMAND(EC_CMD_ROLLBACK_INFO,
- host_command_rollback_info,
- EC_VER_MASK(0));
diff --git a/common/rollback_private.h b/common/rollback_private.h
deleted file mode 100644
index c757882f4f..0000000000
--- a/common/rollback_private.h
+++ /dev/null
@@ -1,33 +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.
- */
-
-/** Internal header file for rollback.
- *
- * EC code should not normally include this. These are exposed so they can be
- * used by unit test code.
- */
-
-#ifndef __CROS_EC_ROLLBACK_PRIVATE_H
-#define __CROS_EC_ROLLBACK_PRIVATE_H
-
-#include "config.h"
-
-/*
- * Note: Do not change this structure without also updating
- * common/firmware_image.S .image.ROLLBACK section.
- */
-struct rollback_data {
- int32_t id; /* Incrementing number to indicate which region to use. */
- int32_t rollback_min_version;
-#ifdef CONFIG_ROLLBACK_SECRET_SIZE
- uint8_t secret[CONFIG_ROLLBACK_SECRET_SIZE];
-#endif
- /* cookie must always be last, as it validates the rest of the data. */
- uint32_t cookie;
-};
-
-int read_rollback(int region, struct rollback_data *data);
-
-#endif /* __CROS_EC_ROLLBACK_PRIVATE_H */
diff --git a/common/rsa.c b/common/rsa.c
deleted file mode 100644
index 10f0afa4b4..0000000000
--- a/common/rsa.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/* Copyright 2014 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.
- */
-
-/*
- * Implementation of RSA signature verification which uses a pre-processed key
- * for computation.
- */
-
-#include "rsa.h"
-#include "sha256.h"
-#include "util.h"
-
-/**
- * a[] -= mod
- */
-static void sub_mod(const struct rsa_public_key *key, uint32_t *a)
-{
- int64_t A = 0;
- uint32_t i;
- for (i = 0; i < RSANUMWORDS; ++i) {
- A += (uint64_t)a[i] - key->n[i];
- a[i] = (uint32_t)A;
- A >>= 32;
- }
-}
-
-/**
- * Return a[] >= mod
- */
-static int ge_mod(const struct rsa_public_key *key, const uint32_t *a)
-{
- uint32_t i;
- for (i = RSANUMWORDS; i;) {
- --i;
- if (a[i] < key->n[i])
- return 0;
- if (a[i] > key->n[i])
- return 1;
- }
- return 1; /* equal */
-}
-
-/**
- * Montgomery c[] += a * b[] / R % mod
- */
-static void mont_mul_add(const struct rsa_public_key *key,
- uint32_t *c,
- const uint32_t a,
- const uint32_t *b)
-{
- uint64_t A = mula32(a, b[0], c[0]);
- uint32_t d0 = (uint32_t)A * key->n0inv;
- uint64_t B = mula32(d0, key->n[0], A);
- uint32_t i;
-
- for (i = 1; i < RSANUMWORDS; ++i) {
- A = mulaa32(a, b[i], c[i], A >> 32);
- B = mulaa32(d0, key->n[i], A, B >> 32);
- c[i - 1] = (uint32_t)B;
- }
-
- A = (A >> 32) + (B >> 32);
-
- c[i - 1] = (uint32_t)A;
-
- if (A >> 32)
- sub_mod(key, c);
-}
-
-#ifdef CONFIG_RSA_EXPONENT_3
-/**
- * Montgomery c[] += 0 * b[] / R % mod
- */
-static void mont_mul_add_0(const struct rsa_public_key *key,
- uint32_t *c,
- const uint32_t *b)
-{
- uint32_t d0 = c[0] * key->n0inv;
- uint64_t B = mula32(d0, key->n[0], c[0]);
- uint32_t i;
-
- for (i = 1; i < RSANUMWORDS; ++i) {
- B = mulaa32(d0, key->n[i], c[i], B >> 32);
- c[i - 1] = (uint32_t)B;
- }
-
- c[i - 1] = B >> 32;
-}
-
-/* Montgomery c[] = a[] * 1 / R % key. */
-static void mont_mul_1(const struct rsa_public_key *key,
- uint32_t *c,
- const uint32_t *a)
-{
- int i;
-
- for (i = 0; i < RSANUMWORDS; ++i)
- c[i] = 0;
-
- mont_mul_add(key, c, 1, a);
- for (i = 1; i < RSANUMWORDS; ++i)
- mont_mul_add_0(key, c, a);
-}
-#endif
-
-/**
- * Montgomery c[] = a[] * b[] / R % mod
- */
-static void mont_mul(const struct rsa_public_key *key,
- uint32_t *c,
- const uint32_t *a,
- const uint32_t *b)
-{
- uint32_t i;
- for (i = 0; i < RSANUMWORDS; ++i)
- c[i] = 0;
-
- for (i = 0; i < RSANUMWORDS; ++i)
- mont_mul_add(key, c, a[i], b);
-}
-
-/**
- * In-place public exponentiation.
- * Exponent depends on the configuration (65537 (default), or 3).
- *
- * @param key Key to use in signing
- * @param inout Input and output big-endian byte array
- * @param workbuf32 Work buffer; caller must verify this is
- * 3 x RSANUMWORDS elements long.
- */
-static void mod_pow(const struct rsa_public_key *key, uint8_t *inout,
- uint32_t *workbuf32)
-{
- uint32_t *a = workbuf32;
- uint32_t *a_r = a + RSANUMWORDS;
- uint32_t *aa_r = a_r + RSANUMWORDS;
- uint32_t *aaa = aa_r; /* Re-use location. */
- int i;
-
- /* Convert from big endian byte array to little endian word array. */
- for (i = 0; i < RSANUMWORDS; ++i) {
- uint32_t tmp =
- (inout[((RSANUMWORDS - 1 - i) * 4) + 0] << 24) |
- (inout[((RSANUMWORDS - 1 - i) * 4) + 1] << 16) |
- (inout[((RSANUMWORDS - 1 - i) * 4) + 2] << 8) |
- (inout[((RSANUMWORDS - 1 - i) * 4) + 3] << 0);
- a[i] = tmp;
- }
-
- /* TODO(drinkcat): This operation could be precomputed to save time. */
- mont_mul(key, a_r, a, key->rr); /* a_r = a * RR / R mod M */
-#ifdef CONFIG_RSA_EXPONENT_3
- mont_mul(key, aa_r, a_r, a_r);
- mont_mul(key, a, aa_r, a_r);
- mont_mul_1(key, aaa, a);
-#else
- /* Exponent 65537 */
- for (i = 0; i < 16; i += 2) {
- mont_mul(key, aa_r, a_r, a_r); /* aa_r = a_r * a_r / R mod M */
- mont_mul(key, a_r, aa_r, aa_r);/* a_r = aa_r * aa_r / R mod M */
- }
- mont_mul(key, aaa, a_r, a); /* aaa = a_r * a / R mod M */
-#endif
-
- /* Make sure aaa < mod; aaa is at most 1x mod too large. */
- if (ge_mod(key, aaa))
- sub_mod(key, aaa);
-
- /* Convert to bigendian byte array */
- for (i = RSANUMWORDS - 1; i >= 0; --i) {
- uint32_t tmp = aaa[i];
- *inout++ = (uint8_t)(tmp >> 24);
- *inout++ = (uint8_t)(tmp >> 16);
- *inout++ = (uint8_t)(tmp >> 8);
- *inout++ = (uint8_t)(tmp >> 0);
- }
-}
-
-/*
- * PKCS#1 padding (from the RSA PKCS#1 v2.1 standard)
- *
- * The DER-encoded padding is defined as follows :
- * 0x00 || 0x01 || PS || 0x00 || T
- *
- * T: DER Encoded DigestInfo value which depends on the hash function used,
- * for SHA-256:
- * (0x)30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || H.
- *
- * Length(T) = 51 octets for SHA-256
- *
- * PS: octet string consisting of {Length(RSA Key) - Length(T) - 3} 0xFF
- */
-static const uint8_t sha256_tail[] = {
- 0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
- 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
- 0x05, 0x00, 0x04, 0x20
-};
-
-#define PKCS_PAD_SIZE (RSANUMBYTES - SHA256_DIGEST_SIZE)
-
-/**
- * Check PKCS#1 padding bytes
- *
- * @param sig Signature to verify
- * @return 0 if the padding is correct.
- */
-static int check_padding(const uint8_t *sig)
-{
- uint8_t *ptr = (uint8_t *)sig;
- int result = 0;
- int i;
-
- /* First 2 bytes are always 0x00 0x01 */
- result |= *ptr++ ^ 0x00;
- result |= *ptr++ ^ 0x01;
-
- /* Then 0xff bytes until the tail */
- for (i = 0; i < PKCS_PAD_SIZE - sizeof(sha256_tail) - 2; i++)
- result |= *ptr++ ^ 0xff;
-
- /* Check the tail. */
- result |= memcmp(ptr, sha256_tail, sizeof(sha256_tail));
-
- return !!result;
-}
-
-/*
- * Verify a SHA256WithRSA PKCS#1 v1.5 signature against an expected
- * SHA256 hash.
- *
- * @param key RSA public key
- * @param signature RSA signature
- * @param sha SHA-256 digest of the content to verify
- * @param workbuf32 Work buffer; caller must verify this is
- * 3 x RSANUMWORDS elements long.
- * @return 0 on failure, 1 on success.
- */
-int rsa_verify(const struct rsa_public_key *key, const uint8_t *signature,
- const uint8_t *sha, uint32_t *workbuf32)
-{
- uint8_t buf[RSANUMBYTES];
-
- /* Copy input to local workspace. */
- memcpy(buf, signature, RSANUMBYTES);
-
- mod_pow(key, buf, workbuf32); /* In-place exponentiation. */
-
- /* Check the PKCS#1 padding */
- if (check_padding(buf) != 0)
- return 0;
-
- /* Check the digest. */
- if (memcmp(buf + PKCS_PAD_SIZE, sha, SHA256_DIGEST_SIZE) != 0)
- return 0;
-
- return 1; /* All checked out OK. */
-}
diff --git a/common/rtc.c b/common/rtc.c
deleted file mode 100644
index 670e86d707..0000000000
--- a/common/rtc.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/* Copyright 2017 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.
- */
-
-/* RTC cross-platform code for Chrome EC */
-/* TODO(chromium:733844): Move this conversion to kernel rtc-cros-ec driver */
-
-#include "rtc.h"
-
-static uint16_t days_since_year_start[12] = {
- 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
-};
-
-/* Conversion between calendar date and seconds eclapsed since 1970-01-01 */
-uint32_t date_to_sec(struct calendar_date time)
-{
- int i;
- uint32_t sec;
-
- sec = time.year * SECS_PER_YEAR;
- for (i = 0; i < time.year; i++) {
- if (IS_LEAP_YEAR(i))
- sec += SECS_PER_DAY;
- }
-
- sec += (days_since_year_start[time.month - 1] +
- (IS_LEAP_YEAR(time.year) && time.month > 2) +
- (time.day - 1)) * SECS_PER_DAY;
-
- /* add the accumulated time in seconds from 1970 to 2000 */
- return sec + SECS_TILL_YEAR_2K;
-}
-
-struct calendar_date sec_to_date(uint32_t sec)
-{
- struct calendar_date time;
- int day_tmp; /* for intermediate calculation */
- int i;
-
- /* RTC time must be after year 2000. */
- sec = (sec > SECS_TILL_YEAR_2K) ? (sec - SECS_TILL_YEAR_2K) : 0;
-
- day_tmp = sec / SECS_PER_DAY;
- time.year = day_tmp / 365;
- day_tmp %= 365;
- for (i = 0; i < time.year; i++) {
- if (IS_LEAP_YEAR(i))
- day_tmp -= 1;
- }
- day_tmp++;
- if (day_tmp <= 0) {
- time.year -= 1;
- day_tmp += IS_LEAP_YEAR(time.year) ? 366 : 365;
- }
- for (i = 1; i < 12; i++) {
- if (days_since_year_start[i] +
- (IS_LEAP_YEAR(time.year) && (i >= 2)) >= day_tmp)
- break;
- }
- time.month = i;
-
- day_tmp -= days_since_year_start[time.month - 1] +
- (IS_LEAP_YEAR(time.year) && (time.month > 2));
- time.day = day_tmp;
-
- return time;
-}
diff --git a/common/rwsig.c b/common/rwsig.c
deleted file mode 100644
index 418a69c1a1..0000000000
--- a/common/rwsig.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/* Copyright 2014 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.
- */
-
-/*
- * Implementation of the RW firmware signature verification and jump.
- */
-
-#include "console.h"
-#include "cros_version.h"
-#include "ec_commands.h"
-#include "flash.h"
-#include "host_command.h"
-#include "rollback.h"
-#include "rsa.h"
-#include "rwsig.h"
-#include "sha256.h"
-#include "shared_mem.h"
-#include "system.h"
-#include "task.h"
-#include "usb_pd.h"
-#include "util.h"
-#include "vb21_struct.h"
-#include "vboot.h"
-
-/* Console output macros */
-#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args)
-
-#if !defined(CONFIG_MAPPED_STORAGE)
-#error rwsig implementation assumes mem-mapped storage.
-#endif
-
-/* RW firmware reset vector */
-static uint32_t * const rw_rst =
- (uint32_t *)(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RW_MEM_OFF + 4);
-
-
-void rwsig_jump_now(void)
-{
- /* Protect all flash before jumping to RW. */
-
- /* This may do nothing if WP is not enabled, RO is not protected. */
- crec_flash_set_protect(EC_FLASH_PROTECT_ALL_NOW, -1);
-
- /*
- * For chips that does not support EC_FLASH_PROTECT_ALL_NOW, use
- * EC_FLASH_PROTECT_ALL_AT_BOOT.
- */
- if (system_is_locked() &&
- !(crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW)) {
- crec_flash_set_protect(EC_FLASH_PROTECT_ALL_AT_BOOT, -1);
-
- if (!(crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW) &&
- crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_AT_BOOT) {
- /*
- * If flash protection is still not enabled (some chips
- * may be able to enable it immediately), reboot.
- */
- cflush();
- system_reset(SYSTEM_RESET_HARD |
- SYSTEM_RESET_PRESERVE_FLAGS);
- }
- }
-
- /* When system is locked, only boot to RW if all flash is protected. */
- if (!system_is_locked() ||
- crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW)
- system_run_image_copy(EC_IMAGE_RW);
-}
-
-/*
- * Check that memory between rwdata[start] and rwdata[len-1] is filled
- * with ones. data, start and len must be aligned on 4-byte boundary.
- */
-static int check_padding(const uint8_t *data,
- unsigned int start, unsigned int len)
-{
- unsigned int i;
- const uint32_t *data32 = (const uint32_t *)data;
-
- if ((start % 4) != 0 || (len % 4) != 0)
- return 0;
-
- for (i = start/4; i < len/4; i++) {
- if (data32[i] != 0xffffffff)
- return 0;
- }
-
- return 1;
-}
-
-int rwsig_check_signature(void)
-{
- struct sha256_ctx ctx;
- int res;
- const struct rsa_public_key *key;
- const uint8_t *sig;
- uint8_t *hash;
- uint32_t *rsa_workbuf = NULL;
- const uint8_t *rwdata = (uint8_t *)CONFIG_PROGRAM_MEMORY_BASE
- + CONFIG_RW_MEM_OFF;
- int good = 0;
-
- unsigned int rwlen;
-#ifdef CONFIG_RWSIG_TYPE_RWSIG
- const struct vb21_packed_key *vb21_key;
- const struct vb21_signature *vb21_sig;
-#endif
-#ifdef CONFIG_ROLLBACK
- int32_t rw_rollback_version;
- int32_t min_rollback_version;
-#endif
-
- /* Check if we have a RW firmware flashed */
- if (*rw_rst == 0xffffffff)
- goto out;
-
- CPRINTS("Verifying RW image...");
-
-#ifdef CONFIG_ROLLBACK
- rw_rollback_version = system_get_rollback_version(EC_IMAGE_RW);
- min_rollback_version = rollback_get_minimum_version();
-
- if (rw_rollback_version < 0 || min_rollback_version < 0 ||
- rw_rollback_version < min_rollback_version) {
- CPRINTS("Rollback error (%d < %d)",
- rw_rollback_version, min_rollback_version);
- goto out;
- }
-#endif
-
- /* Large buffer for RSA computation : could be re-use afterwards... */
- res = SHARED_MEM_ACQUIRE_CHECK(3 * RSANUMBYTES, (char **)&rsa_workbuf);
- if (res) {
- CPRINTS("No memory for RW verification");
- goto out;
- }
-
-#ifdef CONFIG_RWSIG_TYPE_USBPD1
- key = (const struct rsa_public_key *)CONFIG_RO_PUBKEY_ADDR;
- sig = (const uint8_t *)CONFIG_RW_SIG_ADDR;
- rwlen = CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE;
-#elif defined(CONFIG_RWSIG_TYPE_RWSIG)
- vb21_key = vb21_get_packed_key();
- vb21_sig = (const struct vb21_signature *)CONFIG_RW_SIG_ADDR;
-
- if (vb21_key->c.magic != VB21_MAGIC_PACKED_KEY ||
- vb21_key->key_size != sizeof(struct rsa_public_key)) {
- CPRINTS("Invalid key.");
- goto out;
- }
-
- key = (const struct rsa_public_key *)
- ((const uint8_t *)vb21_key + vb21_key->key_offset);
-
- /*
- * TODO(crbug.com/690773): We could verify other parameters such
- * as sig_alg/hash_alg actually matches what we build for.
- */
- if (vb21_sig->c.magic != VB21_MAGIC_SIGNATURE ||
- vb21_sig->sig_size != RSANUMBYTES ||
- vb21_key->sig_alg != vb21_sig->sig_alg ||
- vb21_key->hash_alg != vb21_sig->hash_alg ||
- /* Validity check signature offset and data size. */
- vb21_sig->sig_offset < sizeof(vb21_sig) ||
- (vb21_sig->sig_offset + RSANUMBYTES) > CONFIG_RW_SIG_SIZE ||
- vb21_sig->data_size > (CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE)) {
- CPRINTS("Invalid signature.");
- goto out;
- }
-
- sig = (const uint8_t *)vb21_sig + vb21_sig->sig_offset;
- rwlen = vb21_sig->data_size;
-#endif
-
- /*
- * Check that unverified RW region is actually filled with ones.
- */
- good = check_padding(rwdata, rwlen,
- CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE);
- if (!good) {
- CPRINTS("Invalid padding.");
- goto out;
- }
-
- /* SHA-256 Hash of the RW firmware */
- SHA256_init(&ctx);
- SHA256_update(&ctx, rwdata, rwlen);
- hash = SHA256_final(&ctx);
-
- good = rsa_verify(key, sig, hash, rsa_workbuf);
- if (!good)
- goto out;
-
-#ifdef CONFIG_ROLLBACK
- /*
- * Signature verified: we know that rw_rollback_version is valid, check
- * if rollback information should be updated.
- *
- * If the RW region can be protected independently
- * (CONFIG_FLASH_PROTECT_RW is defined), and system is locked, we only
- * increment the rollback if RW is currently protected.
- *
- * Otherwise, we immediately increment the rollback version.
- */
- if (rw_rollback_version != min_rollback_version
-#ifdef CONFIG_FLASH_PROTECT_RW
- && ((!system_is_locked() ||
- crec_flash_get_protect() &
- EC_FLASH_PROTECT_RW_NOW))
-#endif
- ) {
- /*
- * This will fail if the rollback block is protected (RW image
- * will unprotect that block later on).
- */
- int ret = rollback_update_version(rw_rollback_version);
-
- if (ret == 0) {
- CPRINTS("Rollback updated to %d",
- rw_rollback_version);
- } else if (ret != EC_ERROR_ACCESS_DENIED) {
- CPRINTS("Rollback update error %d", ret);
- good = 0;
- }
- }
-#endif
-out:
- CPRINTS("RW verify %s", good ? "OK" : "FAILED");
-
- if (!good) {
- pd_log_event(PD_EVENT_ACC_RW_FAIL, 0, 0, NULL);
- /* RW firmware is invalid : do not jump there */
- if (system_is_locked())
- system_disable_jump();
- }
- if (rsa_workbuf)
- shared_mem_release(rsa_workbuf);
-
- return good;
-}
-
-#ifdef HAS_TASK_RWSIG
-#define TASK_EVENT_ABORT TASK_EVENT_CUSTOM_BIT(0)
-#define TASK_EVENT_CONTINUE TASK_EVENT_CUSTOM_BIT(1)
-
-static enum rwsig_status rwsig_status;
-
-enum rwsig_status rwsig_get_status(void)
-{
- return rwsig_status;
-}
-
-void rwsig_abort(void)
-{
- task_set_event(TASK_ID_RWSIG, TASK_EVENT_ABORT);
-}
-
-void rwsig_continue(void)
-{
- task_set_event(TASK_ID_RWSIG, TASK_EVENT_CONTINUE);
-}
-
-void rwsig_task(void *u)
-{
- uint32_t evt;
-
- if (system_get_image_copy() != EC_IMAGE_RO)
- goto exit;
-
- /* Stay in RO if we were asked to when reset. */
- if (system_get_reset_flags() & EC_RESET_FLAG_STAY_IN_RO) {
- rwsig_status = RWSIG_ABORTED;
- goto exit;
- }
-
- rwsig_status = RWSIG_IN_PROGRESS;
- if (!rwsig_check_signature()) {
- rwsig_status = RWSIG_INVALID;
- goto exit;
- }
- rwsig_status = RWSIG_VALID;
-
- /* Jump to RW after a timeout */
- evt = task_wait_event(CONFIG_RWSIG_JUMP_TIMEOUT);
-
- /* Jump now if we timed out, or were told to continue. */
- if (evt == TASK_EVENT_TIMER || evt == TASK_EVENT_CONTINUE)
- rwsig_jump_now();
- else
- rwsig_status = RWSIG_ABORTED;
-
-exit:
- /* We're done, yield forever. */
- while (1)
- task_wait_event(-1);
-}
-
-enum ec_status rwsig_cmd_action(struct host_cmd_handler_args *args)
-{
- const struct ec_params_rwsig_action *p = args->params;
-
- switch (p->action) {
- case RWSIG_ACTION_ABORT:
- rwsig_abort();
- break;
- case RWSIG_ACTION_CONTINUE:
- rwsig_continue();
- break;
- default:
- return EC_RES_INVALID_PARAM;
- }
- args->response_size = 0;
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_RWSIG_ACTION,
- rwsig_cmd_action,
- EC_VER_MASK(0));
-
-#else /* !HAS_TASK_RWSIG */
-enum ec_status rwsig_cmd_check_status(struct host_cmd_handler_args *args)
-{
- struct ec_response_rwsig_check_status *r = args->response;
-
- memset(r, 0, sizeof(*r));
- r->status = rwsig_check_signature();
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_RWSIG_CHECK_STATUS,
- rwsig_cmd_check_status,
- EC_VER_MASK(0));
-#endif
diff --git a/common/sha256.c b/common/sha256.c
deleted file mode 120000
index 8c0778c3e6..0000000000
--- a/common/sha256.c
+++ /dev/null
@@ -1 +0,0 @@
-../third_party/sha2//sha256.c \ No newline at end of file
diff --git a/common/shmalloc.c b/common/shmalloc.c
deleted file mode 100644
index b1705b52d1..0000000000
--- a/common/shmalloc.c
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Copyright 2016 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.
- */
-
-/* Malloc/free memory module for Chrome EC */
-#include <stdint.h>
-
-#include "common.h"
-#include "hooks.h"
-#include "link_defs.h"
-#include "shared_mem.h"
-#include "system.h"
-#include "task.h"
-#include "util.h"
-
-static struct mutex shmem_lock;
-
-#ifndef TEST_SHMALLOC
-#define set_map_bit(x)
-#define TEST_GLOBAL static
-#else
-#define TEST_GLOBAL
-#endif
-
-/*
- * At the beginning there is a single free memory chunk which includes all
- * memory available in the system. It then gets fragmented/defragmented based
- * on actual allocations/releases.
- */
-TEST_GLOBAL struct shm_buffer *free_buf_chain;
-
-/* At the beginning there is no allocated buffers */
-TEST_GLOBAL struct shm_buffer *allocced_buf_chain;
-
-/* The size of the biggest ever allocated buffer. */
-static int max_allocated_size;
-
-static void shared_mem_init(void)
-{
- /*
- * Use all the RAM we can. The shared memory buffer is the last thing
- * allocated from the start of RAM, so we can use everything up to the
- * jump data at the end of RAM.
- */
- free_buf_chain = (struct shm_buffer *)__shared_mem_buf;
- free_buf_chain->next_buffer = NULL;
- free_buf_chain->prev_buffer = NULL;
- free_buf_chain->buffer_size = system_usable_ram_end() -
- (uintptr_t)__shared_mem_buf;
-}
-DECLARE_HOOK(HOOK_INIT, shared_mem_init, HOOK_PRIO_FIRST);
-
-/* Called with the mutex lock acquired. */
-static void do_release(struct shm_buffer *ptr)
-{
- struct shm_buffer *pfb;
- struct shm_buffer *top;
- size_t released_size;
-
- /* Take the buffer out of the allocated buffers chain. */
- if (ptr == allocced_buf_chain) {
- if (ptr->next_buffer) {
- set_map_bit(BIT(20));
- ptr->next_buffer->prev_buffer = NULL;
- } else {
- set_map_bit(BIT(21));
- }
- allocced_buf_chain = ptr->next_buffer;
- } else {
- /*
- * Saninty check: verify that the buffer is in the allocated
- * buffers chain.
- */
- for (pfb = allocced_buf_chain->next_buffer;
- pfb;
- pfb = pfb->next_buffer)
- if (pfb == ptr)
- break;
- if (!pfb)
- return;
-
- ptr->prev_buffer->next_buffer = ptr->next_buffer;
- if (ptr->next_buffer) {
- set_map_bit(BIT(22));
- ptr->next_buffer->prev_buffer = ptr->prev_buffer;
- } else {
- set_map_bit(BIT(23));
- }
- }
-
- /*
- * Let's bring the released buffer back into the fold. Cache its size
- * for quick reference.
- */
- released_size = ptr->buffer_size;
- if (!free_buf_chain) {
- /*
- * All memory had been allocated - this buffer is going to be
- * the only available free space.
- */
- set_map_bit(BIT(0));
- free_buf_chain = ptr;
- free_buf_chain->buffer_size = released_size;
- free_buf_chain->next_buffer = NULL;
- free_buf_chain->prev_buffer = NULL;
- return;
- }
-
- if (ptr < free_buf_chain) {
- /*
- * Insert this buffer in the beginning of the chain, possibly
- * merging it with the first buffer of the chain.
- */
- pfb = (struct shm_buffer *)((uintptr_t)ptr + released_size);
- if (pfb == free_buf_chain) {
- set_map_bit(BIT(1));
- /* Merge the two buffers. */
- ptr->buffer_size = free_buf_chain->buffer_size +
- released_size;
- ptr->next_buffer =
- free_buf_chain->next_buffer;
- } else {
- set_map_bit(BIT(2));
- ptr->buffer_size = released_size;
- ptr->next_buffer = free_buf_chain;
- free_buf_chain->prev_buffer = ptr;
- }
- if (ptr->next_buffer) {
- set_map_bit(BIT(3));
- ptr->next_buffer->prev_buffer = ptr;
- } else {
- set_map_bit(BIT(4));
- }
- ptr->prev_buffer = NULL;
- free_buf_chain = ptr;
- return;
- }
-
- /*
- * Need to merge the new free buffer into the existing chain. Find a
- * spot for it, it should be above the highest address buffer which is
- * still below the new one.
- */
- pfb = free_buf_chain;
- while (pfb->next_buffer && (pfb->next_buffer < ptr))
- pfb = pfb->next_buffer;
-
- top = (struct shm_buffer *)((uintptr_t)pfb + pfb->buffer_size);
- if (top == ptr) {
- /*
- * The returned buffer is adjacent to an existing free buffer,
- * below it, merge the two buffers.
- */
- pfb->buffer_size += released_size;
-
- /*
- * Is the returned buffer the exact gap between two free
- * buffers?
- */
- top = (struct shm_buffer *)((uintptr_t)ptr + released_size);
- if (top == pfb->next_buffer) {
- /* Yes, it is. */
- pfb->buffer_size += pfb->next_buffer->buffer_size;
- pfb->next_buffer =
- pfb->next_buffer->next_buffer;
- if (pfb->next_buffer) {
- set_map_bit(BIT(5));
- pfb->next_buffer->prev_buffer = pfb;
- } else {
- set_map_bit(BIT(6));
- }
- }
- return;
- }
-
- top = (struct shm_buffer *)((uintptr_t)ptr + released_size);
- if (top == pfb->next_buffer) {
- /* The new buffer is adjacent with the one right above it. */
- set_map_bit(BIT(7));
- ptr->buffer_size = released_size +
- pfb->next_buffer->buffer_size;
- ptr->next_buffer = pfb->next_buffer->next_buffer;
- } else {
- /* Just include the new free buffer into the chain. */
- set_map_bit(BIT(8));
- ptr->next_buffer = pfb->next_buffer;
- ptr->buffer_size = released_size;
- }
- ptr->prev_buffer = pfb;
- pfb->next_buffer = ptr;
- if (ptr->next_buffer) {
- set_map_bit(BIT(9));
- ptr->next_buffer->prev_buffer = ptr;
- } else {
- set_map_bit(BIT(10));
- }
-}
-
-/* Called with the mutex lock acquired. */
-static int do_acquire(int size, struct shm_buffer **dest_ptr)
-{
- int headroom = 0x10000000; /* we'll never have this much. */
- struct shm_buffer *pfb;
- struct shm_buffer *candidate = 0;
-
- /* To keep things simple let's align the size. */
- size = (size + sizeof(int) - 1) & ~(sizeof(int) - 1);
-
- /* And let's allocate room to fit the buffer header. */
- size += sizeof(struct shm_buffer);
-
- pfb = free_buf_chain;
- while (pfb) {
- if ((pfb->buffer_size >= size) &&
- ((pfb->buffer_size - size) < headroom)) {
- /* this is a new candidate. */
- headroom = pfb->buffer_size - size;
- candidate = pfb;
- }
- pfb = pfb->next_buffer;
- }
-
- if (!candidate) {
- set_map_bit(BIT(11));
- return EC_ERROR_BUSY;
- }
-
- *dest_ptr = candidate;
-
- /* Now let's take the candidate out of the free buffer chain. */
- if (headroom <= sizeof(struct shm_buffer)) {
- /*
- * The entire buffer should be allocated, there is no need to
- * re-define its tail as a new free buffer.
- */
- if (candidate == free_buf_chain) {
- /*
- * The next buffer becomes the head of the free buffer
- * chain.
- */
- free_buf_chain = candidate->next_buffer;
- if (free_buf_chain) {
- set_map_bit(BIT(12));
- free_buf_chain->prev_buffer = 0;
- } else {
- set_map_bit(BIT(13));
- }
- } else {
- candidate->prev_buffer->next_buffer =
- candidate->next_buffer;
- if (candidate->next_buffer) {
- set_map_bit(BIT(14));
- candidate->next_buffer->prev_buffer =
- candidate->prev_buffer;
- } else {
- set_map_bit(BIT(15));
- }
- }
- return EC_SUCCESS;
- }
-
- candidate->buffer_size = size;
-
- /* Candidate's tail becomes a new free buffer. */
- pfb = (struct shm_buffer *)((uintptr_t)candidate + size);
- pfb->buffer_size = headroom;
- pfb->next_buffer = candidate->next_buffer;
- pfb->prev_buffer = candidate->prev_buffer;
-
- if (pfb->next_buffer) {
- set_map_bit(BIT(16));
- pfb->next_buffer->prev_buffer = pfb;
- } else {
- set_map_bit(BIT(17));
- }
-
- if (candidate == free_buf_chain) {
- set_map_bit(BIT(18));
- free_buf_chain = pfb;
- } else {
- set_map_bit(BIT(19));
- pfb->prev_buffer->next_buffer = pfb;
- }
- return EC_SUCCESS;
-}
-
-int shared_mem_size(void)
-{
- struct shm_buffer *pfb;
- size_t max_available = 0;
-
- mutex_lock(&shmem_lock);
-
- /* Find the maximum available buffer size. */
- pfb = free_buf_chain;
- while (pfb) {
- if (pfb->buffer_size > max_available)
- max_available = pfb->buffer_size;
- pfb = pfb->next_buffer;
- }
-
- mutex_unlock(&shmem_lock);
- /* Leave room for shmem header */
- max_available -= sizeof(struct shm_buffer);
- return max_available;
-}
-
-int shared_mem_acquire(int size, char **dest_ptr)
-{
- int rv;
- struct shm_buffer *new_buf;
-
- *dest_ptr = NULL;
-
- if (in_interrupt_context())
- return EC_ERROR_INVAL;
-
- if (!free_buf_chain)
- return EC_ERROR_BUSY;
-
- mutex_lock(&shmem_lock);
- rv = do_acquire(size, &new_buf);
- if (rv == EC_SUCCESS) {
- new_buf->next_buffer = allocced_buf_chain;
- new_buf->prev_buffer = NULL;
- if (allocced_buf_chain)
- allocced_buf_chain->prev_buffer = new_buf;
-
- allocced_buf_chain = new_buf;
-
- *dest_ptr = (void *)(new_buf + 1);
-
- if (size > max_allocated_size)
- max_allocated_size = size;
- }
- mutex_unlock(&shmem_lock);
-
- return rv;
-}
-
-void shared_mem_release(void *ptr)
-{
- if (in_interrupt_context())
- return;
-
- mutex_lock(&shmem_lock);
- do_release((struct shm_buffer *)ptr - 1);
- mutex_unlock(&shmem_lock);
-}
-
-#ifdef CONFIG_CMD_SHMEM
-
-static int command_shmem(int argc, char **argv)
-{
- size_t allocated_size;
- size_t free_size;
- size_t max_free;
- struct shm_buffer *buf;
-
- allocated_size = free_size = max_free = 0;
-
- mutex_lock(&shmem_lock);
-
- for (buf = free_buf_chain; buf; buf = buf->next_buffer) {
- size_t buf_room;
-
- buf_room = buf->buffer_size;
-
- free_size += buf_room;
- if (buf_room > max_free)
- max_free = buf_room;
- }
-
- for (buf = allocced_buf_chain; buf;
- buf = buf->next_buffer)
- allocated_size += buf->buffer_size;
-
- mutex_unlock(&shmem_lock);
-
- ccprintf("Total: %6zd\n", allocated_size + free_size);
- ccprintf("Allocated: %6zd\n", allocated_size);
- ccprintf("Free: %6zd\n", free_size);
- ccprintf("Max free buf: %6zd\n", max_free);
- ccprintf("Max allocated: %6d\n", max_allocated_size);
- return EC_SUCCESS;
-}
-DECLARE_SAFE_CONSOLE_COMMAND(shmem, command_shmem,
- NULL,
- "Print shared memory stats");
-
-#endif /* CONFIG_CMD_SHMEM ^^^^^^^ defined */
diff --git a/common/spi_commands.c b/common/spi_commands.c
deleted file mode 100644
index 1a70a5be82..0000000000
--- a/common/spi_commands.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2015 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.
- *
- * SPI transfer command for debugging SPI devices.
- */
-
-#include "common.h"
-#include "console.h"
-#include "spi.h"
-#include "timer.h"
-#include "util.h"
-
-static int command_spixfer(int argc, char **argv)
-{
- int dev_id;
- uint8_t offset;
- int v = 0;
- uint8_t data[32];
- char *e;
- int rv = 0;
-
- if (argc != 5)
- return EC_ERROR_PARAM_COUNT;
-
- dev_id = strtoi(argv[2], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2;
-
- offset = strtoi(argv[3], &e, 0);
- if (*e)
- return EC_ERROR_PARAM3;
-
- v = strtoi(argv[4], &e, 0);
- if (*e)
- return EC_ERROR_PARAM4;
-
- if (strcasecmp(argv[1], "rlen") == 0) {
- uint8_t cmd = 0x80 | offset;
-
- /* Arbitrary length read; param4 = len */
- if (v < 0 || v > sizeof(data))
- return EC_ERROR_PARAM4;
-
- rv = spi_transaction(&spi_devices[dev_id], &cmd, 1, data, v);
-
- if (!rv)
- ccprintf("Data: %ph\n", HEX_BUF(data, v));
-
- } else if (strcasecmp(argv[1], "w") == 0) {
- /* 8-bit write */
- uint8_t cmd[2] = { offset, v };
-
- rv = spi_transaction(&spi_devices[dev_id], cmd, 2, NULL, 0);
-
- /*
- * Some SPI device needs a delay before accepting other
- * commands, otherwise the write might be ignored.
- */
- msleep(1);
- } else {
- return EC_ERROR_PARAM1;
- }
-
- return rv;
-}
-DECLARE_CONSOLE_COMMAND(spixfer, command_spixfer,
- "rlen/w id offset [value | len]",
- "Read write spi. id is spi_devices array index");
-
diff --git a/common/spi_flash.c b/common/spi_flash.c
deleted file mode 100644
index e202e1e17d..0000000000
--- a/common/spi_flash.c
+++ /dev/null
@@ -1,707 +0,0 @@
-/*
- * Copyright 2014 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.
- *
- * SPI flash driver for Chrome EC.
- */
-
-#include "common.h"
-#include "console.h"
-#include "host_command.h"
-#include "shared_mem.h"
-#include "spi.h"
-#include "spi_flash.h"
-#include "spi_flash_reg.h"
-#include "timer.h"
-#include "util.h"
-#include "watchdog.h"
-#include "ec_commands.h"
-#include "flash.h"
-
-/*
- * Time to sleep when chip is busy
- */
-#define SPI_FLASH_SLEEP_USEC 100
-
-/*
- * This is the max time for 32kb flash erase
- */
-#define SPI_FLASH_TIMEOUT_USEC (800*MSEC)
-
-/* Internal buffer used by SPI flash driver */
-static uint8_t buf[SPI_FLASH_MAX_MESSAGE_SIZE];
-
-/**
- * Waits for chip to finish current operation. Must be called after
- * erase/write operations to ensure successive commands are executed.
- *
- * @return EC_SUCCESS or error on timeout
- */
-int spi_flash_wait(void)
-{
- timestamp_t timeout;
-
- timeout.val = get_time().val + SPI_FLASH_TIMEOUT_USEC;
- /* Wait until chip is not busy */
- while (spi_flash_get_status1() & SPI_FLASH_SR1_BUSY) {
- usleep(SPI_FLASH_SLEEP_USEC);
-
- if (get_time().val > timeout.val)
- return EC_ERROR_TIMEOUT;
- }
-
- return EC_SUCCESS;
-}
-
-/**
- * Set the write enable latch
- */
-static int spi_flash_write_enable(void)
-{
- uint8_t cmd = SPI_FLASH_WRITE_ENABLE;
- return spi_transaction(SPI_FLASH_DEVICE, &cmd, 1, NULL, 0);
-}
-
-/**
- * Returns the contents of SPI flash status register 1
- * @return register contents or 0xff on error
- */
-uint8_t spi_flash_get_status1(void)
-{
- uint8_t cmd = SPI_FLASH_READ_SR1;
- uint8_t resp;
-
- if (spi_transaction(SPI_FLASH_DEVICE, &cmd, 1, &resp, 1) != EC_SUCCESS)
- return 0xff;
-
- return resp;
-}
-
-/**
- * Returns the contents of SPI flash status register 2
- * @return register contents or 0xff on error
- */
-uint8_t spi_flash_get_status2(void)
-{
- uint8_t cmd = SPI_FLASH_READ_SR2;
- uint8_t resp;
-
- /* Second status register not present */
-#ifndef CONFIG_SPI_FLASH_HAS_SR2
- return 0;
-#endif
-
- if (spi_transaction(SPI_FLASH_DEVICE, &cmd, 1, &resp, 1) != EC_SUCCESS)
- return 0xff;
-
- return resp;
-}
-
-/**
- * Sets the SPI flash status registers (non-volatile bits only)
- * Pass reg2 == -1 to only set reg1.
- *
- * @param reg1 Status register 1
- * @param reg2 Status register 2 (optional)
- *
- * @return EC_SUCCESS, or non-zero if any error.
- */
-int spi_flash_set_status(int reg1, int reg2)
-{
- uint8_t cmd[3] = {SPI_FLASH_WRITE_SR, reg1, reg2};
- int rv = EC_SUCCESS;
-
- /* fail if both HW pin is asserted and SRP(s) is 1 */
- if (spi_flash_check_wp() != SPI_WP_NONE &&
- (crec_flash_get_protect() &
- EC_FLASH_PROTECT_GPIO_ASSERTED) != 0)
- return EC_ERROR_ACCESS_DENIED;
-
- /* Enable writing to SPI flash */
- rv = spi_flash_write_enable();
- if (rv)
- return rv;
-
- /* Second status register not present */
-#ifndef CONFIG_SPI_FLASH_HAS_SR2
- reg2 = -1;
-#endif
-
- if (reg2 == -1)
- rv = spi_transaction(SPI_FLASH_DEVICE, cmd, 2, NULL, 0);
- else
- rv = spi_transaction(SPI_FLASH_DEVICE, cmd, 3, NULL, 0);
- if (rv)
- return rv;
-
- /* SRP update takes up to 10 ms, so wait for transaction to finish */
- spi_flash_wait();
-
- return rv;
-}
-
-/**
- * Returns the content of SPI flash
- *
- * @param buf_usr Buffer to write flash contents
- * @param offset Flash offset to start reading from
- * @param bytes Number of bytes to read.
- *
- * @return EC_SUCCESS, or non-zero if any error.
- */
-int spi_flash_read(uint8_t *buf_usr, unsigned int offset, unsigned int bytes)
-{
- int i, read_size, ret, spi_addr;
- uint8_t cmd[4];
- if (offset + bytes > CONFIG_FLASH_SIZE_BYTES)
- return EC_ERROR_INVAL;
- cmd[0] = SPI_FLASH_READ;
- for (i = 0; i < bytes; i += read_size) {
- spi_addr = offset + i;
- cmd[1] = (spi_addr >> 16) & 0xFF;
- cmd[2] = (spi_addr >> 8) & 0xFF;
- cmd[3] = spi_addr & 0xFF;
- read_size = MIN((bytes - i), SPI_FLASH_MAX_READ_SIZE);
- ret = spi_transaction(SPI_FLASH_DEVICE,
- cmd,
- 4,
- buf_usr + i,
- read_size);
- if (ret != EC_SUCCESS)
- break;
- msleep(CONFIG_SPI_FLASH_READ_WAIT_MS);
- }
- return ret;
-}
-
-/**
- * Erase a block of SPI flash.
- *
- * @param offset Flash offset to start erasing
- * @param block Block size in kb (4 or 32)
- *
- * @return EC_SUCCESS, or non-zero if any error.
- */
-static int spi_flash_erase_block(unsigned int offset, unsigned int block)
-{
- uint8_t cmd[4];
- int rv = EC_SUCCESS;
-
- /* Invalid block size */
- if (block != 4 && block != 32)
- return EC_ERROR_INVAL;
-
- /* Not block aligned */
- if ((offset % (block * 1024)) != 0)
- return EC_ERROR_INVAL;
-
- /* Enable writing to SPI flash */
- rv = spi_flash_write_enable();
- if (rv)
- return rv;
-
- /* Compose instruction */
- cmd[0] = (block == 4) ? SPI_FLASH_ERASE_4KB : SPI_FLASH_ERASE_32KB;
- cmd[1] = (offset >> 16) & 0xFF;
- cmd[2] = (offset >> 8) & 0xFF;
- cmd[3] = offset & 0xFF;
-
- rv = spi_transaction(SPI_FLASH_DEVICE, cmd, 4, NULL, 0);
- if (rv)
- return rv;
-
- /* Wait for previous operation to complete */
- return spi_flash_wait();
-}
-
-/**
- * Erase SPI flash.
- *
- * @param offset Flash offset to start erasing
- * @param bytes Number of bytes to erase
- *
- * @return EC_SUCCESS, or non-zero if any error.
- */
-int spi_flash_erase(unsigned int offset, unsigned int bytes)
-{
- int rv = EC_SUCCESS;
-
- /* Invalid input */
- if (offset + bytes > CONFIG_FLASH_SIZE_BYTES)
- return EC_ERROR_INVAL;
-
- /* Not aligned to sector (4kb) */
- if (offset % 4096 || bytes % 4096)
- return EC_ERROR_INVAL;
-
- /* Largest unit is block (32kb) */
- if (offset % (32 * 1024) == 0) {
- while (bytes != (bytes % (32 * 1024))) {
- rv = spi_flash_erase_block(offset, 32);
- if (rv)
- return rv;
-
- bytes -= 32 * 1024;
- offset += 32 * 1024;
- /*
- * Refresh watchdog since we may be erasing a large
- * number of blocks.
- */
- watchdog_reload();
- }
- }
-
- /* Largest unit is sector (4kb) */
- while (bytes != (bytes % (4 * 1024))) {
- rv = spi_flash_erase_block(offset, 4);
- if (rv)
- return rv;
-
- bytes -= 4 * 1024;
- offset += 4 * 1024;
- }
-
- return rv;
-}
-
-/**
- * Write to SPI flash. Assumes already erased.
- * Limited to SPI_FLASH_MAX_WRITE_SIZE by chip.
- *
- * @param offset Flash offset to write
- * @param bytes Number of bytes to write
- * @param data Data to write to flash
- *
- * @return EC_SUCCESS, or non-zero if any error.
- */
-int spi_flash_write(unsigned int offset, unsigned int bytes,
- const uint8_t *data)
-{
- int rv, write_size;
-
- /* Invalid input */
- if (!data || offset + bytes > CONFIG_FLASH_SIZE_BYTES ||
- bytes > SPI_FLASH_MAX_WRITE_SIZE)
- return EC_ERROR_INVAL;
-
- while (bytes > 0) {
- watchdog_reload();
- /* Write length can not go beyond the end of the flash page */
- write_size = MIN(bytes, SPI_FLASH_MAX_WRITE_SIZE -
- (offset & (SPI_FLASH_MAX_WRITE_SIZE - 1)));
-
- /* Wait for previous operation to complete */
- rv = spi_flash_wait();
- if (rv)
- return rv;
-
- /* Enable writing to SPI flash */
- rv = spi_flash_write_enable();
- if (rv)
- return rv;
-
- /* Copy data to send buffer; buffers may overlap */
- memmove(buf + 4, data, write_size);
-
- /* Compose instruction */
- buf[0] = SPI_FLASH_PAGE_PRGRM;
- buf[1] = (offset) >> 16;
- buf[2] = (offset) >> 8;
- buf[3] = offset;
-
- rv = spi_transaction(SPI_FLASH_DEVICE,
- buf, 4 + write_size, NULL, 0);
- if (rv)
- return rv;
-
- data += write_size;
- offset += write_size;
- bytes -= write_size;
- }
-
- /* Wait for previous operation to complete */
- return spi_flash_wait();
-}
-
-/**
- * Gets the SPI flash JEDEC ID (manufacturer ID, memory type, and capacity)
- *
- * @param dest Destination buffer; must be 3 bytes long
- * @return EC_SUCCESS or non-zero on error
- */
-int spi_flash_get_jedec_id(uint8_t *dest)
-{
- uint8_t cmd = SPI_FLASH_JEDEC_ID;
-
- return spi_transaction(SPI_FLASH_DEVICE, &cmd, 1, dest, 3);
-}
-
-/**
- * Gets the SPI flash manufacturer and device ID
- *
- * @param dest Destination buffer; must be 2 bytes long
- * @return EC_SUCCESS or non-zero on error
- */
-int spi_flash_get_mfr_dev_id(uint8_t *dest)
-{
- uint8_t cmd[4] = {SPI_FLASH_MFR_DEV_ID, 0, 0, 0};
-
- return spi_transaction(SPI_FLASH_DEVICE, cmd, sizeof(cmd), dest, 2);
-}
-
-/**
- * Gets the SPI flash unique ID (serial)
- *
- * @param dest Destination buffer; must be 8 bytes long
- * @return EC_SUCCESS or non-zero on error
- */
-int spi_flash_get_unique_id(uint8_t *dest)
-{
- uint8_t cmd[5] = {SPI_FLASH_UNIQUE_ID, 0, 0, 0, 0};
-
- return spi_transaction(SPI_FLASH_DEVICE, cmd, sizeof(cmd), dest, 8);
-}
-
-/**
- * Check for SPI flash status register write protection
- * Cannot sample WP pin, so caller should sample it if necessary, if
- * SPI_WP_HARDWARE is returned.
- *
- * @return enum spi_flash_wp status based on protection
- */
-enum spi_flash_wp spi_flash_check_wp(void)
-{
- int sr1_prot = spi_flash_get_status1() & SPI_FLASH_SR1_SRP0;
- int sr2_prot = spi_flash_get_status2() & SPI_FLASH_SR2_SRP1;
-
- if (sr2_prot)
- return sr1_prot ? SPI_WP_PERMANENT : SPI_WP_POWER_CYCLE;
- else if (sr1_prot)
- return SPI_WP_HARDWARE;
-
- return SPI_WP_NONE;
-}
-
-/**
- * Set SPI flash status register write protection
- *
- * @param wp Status register write protection mode
- *
- * @return EC_SUCCESS for no protection, or non-zero if error.
- */
-int spi_flash_set_wp(enum spi_flash_wp w)
-{
- int sr1 = spi_flash_get_status1();
- int sr2 = spi_flash_get_status2();
-
- switch (w) {
- case SPI_WP_NONE:
- sr1 &= ~SPI_FLASH_SR1_SRP0;
- sr2 &= ~SPI_FLASH_SR2_SRP1;
- break;
- case SPI_WP_HARDWARE:
- sr1 |= SPI_FLASH_SR1_SRP0;
- sr2 &= ~SPI_FLASH_SR2_SRP1;
- break;
- case SPI_WP_POWER_CYCLE:
- sr1 &= ~SPI_FLASH_SR1_SRP0;
- sr2 |= SPI_FLASH_SR2_SRP1;
- break;
- case SPI_WP_PERMANENT:
- sr1 |= SPI_FLASH_SR1_SRP0;
- sr2 |= SPI_FLASH_SR2_SRP1;
- break;
- default:
- return EC_ERROR_INVAL;
- }
-
- return spi_flash_set_status(sr1, sr2);
-}
-
-/**
- * Check for SPI flash block write protection
- *
- * @param offset Flash block offset to check
- * @param bytes Flash block length to check
- *
- * @return EC_SUCCESS for no protection, or non-zero if error.
- */
-int spi_flash_check_protect(unsigned int offset, unsigned int bytes)
-{
- uint8_t sr1 = spi_flash_get_status1();
- uint8_t sr2 = spi_flash_get_status2();
- unsigned int start;
- unsigned int len;
- int rv = EC_SUCCESS;
-
- /* Invalid value */
- if (sr1 == 0xff || sr2 == 0xff ||
- offset + bytes > CONFIG_FLASH_SIZE_BYTES)
- return EC_ERROR_INVAL;
-
- /* Compute current protect range */
- rv = spi_flash_reg_to_protect(sr1, sr2, &start, &len);
- if (rv)
- return rv;
-
- /* Check if ranges overlap */
- if (MAX(start, offset) < MIN(start + len, offset + bytes))
- return EC_ERROR_ACCESS_DENIED;
-
- return EC_SUCCESS;
-}
-
-/**
- * Set SPI flash block write protection
- * If offset == bytes == 0, remove protection.
- *
- * @param offset Flash block offset to protect
- * @param bytes Flash block length to protect
- *
- * @return EC_SUCCESS, or non-zero if error.
- */
-int spi_flash_set_protect(unsigned int offset, unsigned int bytes)
-{
- int rv;
- uint8_t sr1 = spi_flash_get_status1();
- uint8_t sr2 = spi_flash_get_status2();
-
- /* Invalid values */
- if (sr1 == 0xff || sr2 == 0xff ||
- offset + bytes > CONFIG_FLASH_SIZE_BYTES)
- return EC_ERROR_INVAL;
-
- /* Compute desired protect range */
- rv = spi_flash_protect_to_reg(offset, bytes, &sr1, &sr2);
- if (rv)
- return rv;
-
- return spi_flash_set_status(sr1, sr2);
-}
-
-static int command_spi_flashinfo(int argc, char **argv)
-{
- uint8_t jedec[3];
- uint8_t unique[8];
- int rv;
-
- /* TODO(tomhughes): use board function to get devices. */
- spi_enable(SPI_FLASH_DEVICE, 1);
-
- /* Wait for previous operation to complete */
- rv = spi_flash_wait();
- if (rv)
- return rv;
-
- spi_flash_get_jedec_id(jedec);
- spi_flash_get_unique_id(unique);
-
- ccprintf("Manufacturer ID: %02x\nDevice ID: %02x %02x\n",
- jedec[0], jedec[1], jedec[2]);
- ccprintf("Unique ID: %02x %02x %02x %02x %02x %02x %02x %02x\n",
- unique[0], unique[1], unique[2], unique[3],
- unique[4], unique[5], unique[6], unique[7]);
- ccprintf("Capacity: %4d kB\n", SPI_FLASH_SIZE(jedec[2]) / 1024);
-
- return rv;
-}
-DECLARE_CONSOLE_COMMAND(spi_flashinfo, command_spi_flashinfo,
- NULL,
- "Print SPI flash info");
-
-#ifdef CONFIG_HOSTCMD_FLASH_SPI_INFO
-static enum ec_status flash_command_spi_info(struct host_cmd_handler_args *args)
-{
- struct ec_response_flash_spi_info *r = args->response;
-
- spi_flash_get_jedec_id(r->jedec);
- r->reserved0 = 0;
- spi_flash_get_mfr_dev_id(r->mfr_dev_id);
- r->sr1 = spi_flash_get_status1();
- r->sr2 = spi_flash_get_status2();
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_FLASH_SPI_INFO,
- flash_command_spi_info,
- EC_VER_MASK(0));
-#endif /* CONFIG_HOSTCMD_FLASH_SPI_INFO */
-
-#ifdef CONFIG_CMD_SPI_FLASH
-static int command_spi_flasherase(int argc, char **argv)
-{
- int offset = -1;
- int bytes = 4096;
- int rv = parse_offset_size(argc, argv, 1, &offset, &bytes);
-
- if (rv)
- return rv;
-
- spi_enable(SPI_FLASH_DEVICE, 1);
-
- /* Chip has protection */
- if (spi_flash_check_protect(offset, bytes))
- return EC_ERROR_ACCESS_DENIED;
-
- ccprintf("Erasing %d bytes at 0x%x...\n", bytes, offset);
- return spi_flash_erase(offset, bytes);
-}
-DECLARE_CONSOLE_COMMAND(spi_flasherase, command_spi_flasherase,
- "offset [bytes]",
- "Erase flash");
-
-static int command_spi_flashwrite(int argc, char **argv)
-{
- int offset = -1;
- int bytes = SPI_FLASH_MAX_WRITE_SIZE;
- int write_len;
- int rv = EC_SUCCESS;
- int i;
-
- rv = parse_offset_size(argc, argv, 1, &offset, &bytes);
- if (rv)
- return rv;
-
- spi_enable(SPI_FLASH_DEVICE, 1);
-
- /* Chip has protection */
- if (spi_flash_check_protect(offset, bytes))
- return EC_ERROR_ACCESS_DENIED;
-
- /* Fill the data buffer with a pattern */
- for (i = 0; i < SPI_FLASH_MAX_WRITE_SIZE; i++)
- buf[i] = i;
-
- ccprintf("Writing %d bytes to 0x%x...\n", bytes, offset);
- while (bytes > 0) {
- /* First write multiples of 256, then (bytes % 256) last */
- write_len = ((bytes % SPI_FLASH_MAX_WRITE_SIZE) == bytes) ?
- bytes : SPI_FLASH_MAX_WRITE_SIZE;
-
- /* Perform write */
- rv = spi_flash_write(offset, write_len, buf);
- if (rv)
- return rv;
-
- offset += write_len;
- bytes -= write_len;
- }
-
- ASSERT(bytes == 0);
-
- return rv;
-}
-DECLARE_CONSOLE_COMMAND(spi_flashwrite, command_spi_flashwrite,
- "offset [bytes]",
- "Write pattern to flash");
-
-static int command_spi_flashread(int argc, char **argv)
-{
- int i;
- int offset = -1;
- int bytes = -1;
- int read_len;
- int rv;
-
- rv = parse_offset_size(argc, argv, 1, &offset, &bytes);
- if (rv)
- return rv;
-
- spi_enable(SPI_FLASH_DEVICE, 1);
-
- /* Can't read past size of memory */
- if (offset + bytes > CONFIG_FLASH_SIZE_BYTES)
- return EC_ERROR_INVAL;
-
- /* Wait for previous operation to complete */
- rv = spi_flash_wait();
- if (rv)
- return rv;
-
- ccprintf("Reading %d bytes from 0x%x...\n", bytes, offset);
- /* Read <= 256 bytes to avoid allocating another buffer */
- while (bytes > 0) {
- watchdog_reload();
-
- /* First read (bytes % 256), then in multiples of 256 */
- read_len = (bytes % SPI_FLASH_MAX_READ_SIZE) ?
- (bytes % SPI_FLASH_MAX_READ_SIZE) :
- SPI_FLASH_MAX_READ_SIZE;
-
- rv = spi_flash_read(buf, offset, read_len);
- if (rv)
- return rv;
-
- for (i = 0; i < read_len; i++) {
- if (i % 16 == 0)
- ccprintf("%02x:", offset + i);
-
- ccprintf(" %02x", buf[i]);
-
- if (i % 16 == 15 || i == read_len - 1)
- ccputs("\n");
- }
-
- offset += read_len;
- bytes -= read_len;
- }
-
- ASSERT(bytes == 0);
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(spi_flashread, command_spi_flashread,
- "offset bytes",
- "Read flash");
-
-static int command_spi_flashread_sr(int argc, char **argv)
-{
- spi_enable(SPI_FLASH_DEVICE, 1);
-
- ccprintf("Status Register 1: 0x%02x\n", spi_flash_get_status1());
- ccprintf("Status Register 2: 0x%02x\n", spi_flash_get_status2());
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(spi_flash_rsr, command_spi_flashread_sr,
- NULL,
- "Read status registers");
-
-static int command_spi_flashwrite_sr(int argc, char **argv)
-{
- int val1 = 0;
- int val2 = 0;
- int rv = parse_offset_size(argc, argv, 1, &val1, &val2);
-
- if (rv)
- return rv;
-
- spi_enable(SPI_FLASH_DEVICE, 1);
-
- ccprintf("Writing 0x%02x to status register 1, ", val1);
- ccprintf("0x%02x to status register 2...\n", val2);
- return spi_flash_set_status(val1, val2);
-}
-DECLARE_CONSOLE_COMMAND(spi_flash_wsr, command_spi_flashwrite_sr,
- "value1 value2",
- "Write to status registers");
-
-static int command_spi_flashprotect(int argc, char **argv)
-{
- int val1 = 0;
- int val2 = 0;
- int rv = parse_offset_size(argc, argv, 1, &val1, &val2);
-
- if (rv)
- return rv;
-
- spi_enable(SPI_FLASH_DEVICE, 1);
-
- ccprintf("Setting protection for 0x%06x to 0x%06x\n", val1, val1+val2);
- return spi_flash_set_protect(val1, val2);
-}
-DECLARE_CONSOLE_COMMAND(spi_flash_prot, command_spi_flashprotect,
- "offset len",
- "Set block protection");
-#endif
diff --git a/common/spi_flash_reg.c b/common/spi_flash_reg.c
deleted file mode 100644
index ee8d31fa06..0000000000
--- a/common/spi_flash_reg.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright 2015 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.
- *
- * SPI flash protection register translation functions for Chrome OS EC.
- */
-
-#include "common.h"
-#include "spi_flash_reg.h"
-#include "util.h"
-
-/* Bit state for protect range table */
-enum bit_state {
- OFF = 0,
- ON = 1,
- IGN = -1, /* Don't care / Ignore */
-};
-
-struct protect_range {
- enum bit_state cmp;
- enum bit_state sec;
- enum bit_state tb;
- enum bit_state bp[3]; /* Ordered {BP2, BP1, BP0} */
- uint32_t protect_start;
- uint32_t protect_len;
-};
-
-/* Compare macro for (x =? b) for 'IGN' comparison */
-#define COMPARE_BIT(a, b) ((a) != IGN && (a) != !!(b))
-/* Assignment macro where 'IGN' = 0 */
-#define GET_BIT(a) ((a) == IGN ? 0 : (a))
-
-/*
- * Define flags and protect table for each SPI ROM part. It's not necessary
- * to define all ranges in the datasheet since we'll usually protect only
- * none or half of the ROM. The table is searched sequentially, so ordering
- * according to likely configurations improves performance slightly.
- */
-#if defined(CONFIG_SPI_FLASH_W25X40) || defined(CONFIG_SPI_FLASH_GD25Q41B)
-static const struct protect_range spi_flash_protect_ranges[] = {
- { IGN, IGN, IGN, { 0, 0, 0 }, 0, 0 }, /* No protection */
- { IGN, IGN, 1, { 0, 1, 1 }, 0, 0x40000 }, /* Lower 1/2 */
- { IGN, IGN, 1, { 0, 1, 0 }, 0, 0x20000 }, /* Lower 1/4 */
-};
-
-#elif defined(CONFIG_SPI_FLASH_W25Q40) || defined(CONFIG_SPI_FLASH_GD25LQ40)
-/* Verified for W25Q40BV and W25Q40EW */
-/* For GD25LQ40, BP3 and BP4 have same meaning as TB and SEC */
-static const struct protect_range spi_flash_protect_ranges[] = {
- /* CMP = 0 */
- { 0, IGN, IGN, { 0, 0, 0 }, 0, 0 }, /* No protection */
- { 0, 0, 1, { 0, 1, 0 }, 0, 0x20000 }, /* Lower 1/4 */
- { 0, 0, 1, { 0, 1, 1 }, 0, 0x40000 }, /* Lower 1/2 */
- /* CMP = 1 */
- { 1, 0, 0, { 0, 1, 1 }, 0, 0x40000 }, /* Lower 1/2 */
- { 1, 0, IGN, { 1, IGN, IGN }, 0, 0 }, /* None (W25Q40EW only) */
-};
-
-#elif defined(CONFIG_SPI_FLASH_W25Q64)
-static const struct protect_range spi_flash_protect_ranges[] = {
- { 0, IGN, IGN, { 0, 0, 0 }, 0, 0 }, /* No protection */
- { 0, 0, 1, { 1, 1, 0 }, 0, 0x400000 }, /* Lower 1/2 */
- { 0, 0, 1, { 1, 0, 1 }, 0, 0x200000 }, /* Lower 1/4 */
-};
-
-#elif defined(CONFIG_SPI_FLASH_W25Q80)
-static const struct protect_range spi_flash_protect_ranges[] = {
- /* CMP = 0 */
- { 0, IGN, IGN, { 0, 0, 0 }, 0, 0 }, /* No protection */
- { 0, 0, 1, { 0, 1, 0 }, 0, 0x20000 }, /* Lower 1/8 */
- { 0, 0, 1, { 0, 1, 1 }, 0, 0x40000 }, /* Lower 1/4 */
- { 0, 0, 1, { 1, 0, 0 }, 0, 0x80000 }, /* Lower 1/2 */
-};
-#elif defined(CONFIG_SPI_FLASH_W25Q128)
-static const struct protect_range spi_flash_protect_ranges[] = {
- /* CMP = 0 */
- { 0, IGN, IGN, { 0, 0, 0 }, 0, 0 }, /* No protection */
- { 0, 0, 1, { 1, 0, 0 }, 0, 0x20000 }, /* Lower 1/8 */
- { 0, 0, 1, { 1, 0, 1 }, 0, 0x40000 }, /* Lower 1/4 */
- { 0, 0, 1, { 1, 1, 0 }, 0, 0x80000 }, /* Lower 1/2 */
-};
-#endif
-
-/**
- * Computes block write protection range from registers
- * Returns start == len == 0 for no protection
- *
- * @param sr1 Status register 1
- * @param sr2 Status register 2
- * @param start Output pointer for protection start offset
- * @param len Output pointer for protection length
- *
- * @return EC_SUCCESS, or non-zero if any error.
- */
-int spi_flash_reg_to_protect(uint8_t sr1, uint8_t sr2, unsigned int *start,
- unsigned int *len)
-{
- const struct protect_range *range;
- int i;
- uint8_t cmp;
- uint8_t sec;
- uint8_t tb;
- uint8_t bp;
-
- /* Determine flags */
- cmp = (sr2 & SPI_FLASH_SR2_CMP) ? 1 : 0;
- sec = (sr1 & SPI_FLASH_SR1_SEC) ? 1 : 0;
- tb = (sr1 & SPI_FLASH_SR1_TB) ? 1 : 0;
- bp = (sr1 & (SPI_FLASH_SR1_BP2 | SPI_FLASH_SR1_BP1 | SPI_FLASH_SR1_BP0))
- >> 2;
-
- /* Bad pointers or invalid data */
- if (!start || !len || sr1 == 0xff || sr2 == 0xff)
- return EC_ERROR_INVAL;
-
- for (i = 0; i < ARRAY_SIZE(spi_flash_protect_ranges); ++i) {
- range = &spi_flash_protect_ranges[i];
- if (COMPARE_BIT(range->cmp, cmp))
- continue;
- if (COMPARE_BIT(range->sec, sec))
- continue;
- if (COMPARE_BIT(range->tb, tb))
- continue;
- if (COMPARE_BIT(range->bp[0], bp & 0x4))
- continue;
- if (COMPARE_BIT(range->bp[1], bp & 0x2))
- continue;
- if (COMPARE_BIT(range->bp[2], bp & 0x1))
- continue;
-
- *start = range->protect_start;
- *len = range->protect_len;
- return EC_SUCCESS;
- }
-
- /* Invalid range, or valid range missing from our table */
- return EC_ERROR_INVAL;
-}
-
-/**
- * Computes block write protection registers from range
- *
- * @param start Desired protection start offset
- * @param len Desired protection length
- * @param sr1 Output pointer for status register 1
- * @param sr2 Output pointer for status register 2
- *
- * @return EC_SUCCESS, or non-zero if any error.
- */
-int spi_flash_protect_to_reg(unsigned int start, unsigned int len, uint8_t *sr1,
- uint8_t *sr2)
-{
- const struct protect_range *range;
- int i;
- char cmp = 0;
- char sec = 0;
- char tb = 0;
- char bp = 0;
-
- /* Bad pointers */
- if (!sr1 || !sr2)
- return EC_ERROR_INVAL;
-
- /* Invalid data */
- if ((start && !len) || start + len > CONFIG_FLASH_SIZE_BYTES)
- return EC_ERROR_INVAL;
-
- for (i = 0; i < ARRAY_SIZE(spi_flash_protect_ranges); ++i) {
- range = &spi_flash_protect_ranges[i];
- if (range->protect_start == start &&
- range->protect_len == len) {
- cmp = GET_BIT(range->cmp);
- sec = GET_BIT(range->sec);
- tb = GET_BIT(range->tb);
- bp = GET_BIT(range->bp[0]) << 2 |
- GET_BIT(range->bp[1]) << 1 |
- GET_BIT(range->bp[2]);
-
- *sr1 = (sec ? SPI_FLASH_SR1_SEC : 0) |
- (tb ? SPI_FLASH_SR1_TB : 0) |
- (bp << 2);
- *sr2 = (cmp ? SPI_FLASH_SR2_CMP : 0);
- return EC_SUCCESS;
- }
- }
-
- /* Invalid range, or valid range missing from our table */
- return EC_ERROR_INVAL;
-}
diff --git a/common/spi_nor.c b/common/spi_nor.c
deleted file mode 100644
index 0a719d63b3..0000000000
--- a/common/spi_nor.c
+++ /dev/null
@@ -1,1091 +0,0 @@
-/* Copyright 2015 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.
- */
-
-/* SFDP-based Serial NOR flash device module for Chrome EC */
-
-#include "common.h"
-#include "console.h"
-#include "spi_nor.h"
-#include "shared_mem.h"
-#include "util.h"
-#include "task.h"
-#include "spi.h"
-#include "sfdp.h"
-#include "timer.h"
-#include "watchdog.h"
-
-#ifdef CONFIG_SPI_NOR_DEBUG
-#define CPRINTS(dev, string, args...) \
- cprints(CC_SPI, "SPI NOR %s: " string, (dev)->name, ## args)
-#else
-#define CPRINTS(dev, string, args...)
-#endif
-
-/* Time to sleep while serial NOR flash write is in progress. */
-#define SPI_NOR_WIP_SLEEP_USEC 10
-
-/* This driver only supports v1.* SFDP. */
-#define SPI_NOR_SUPPORTED_SFDP_MAJOR_VERSION 1
-
-/* Ensure a Serial NOR Flash read command in 4B addressing mode fits. */
-BUILD_ASSERT(CONFIG_SPI_NOR_MAX_READ_SIZE + 5 <=
- CONFIG_SPI_NOR_MAX_MESSAGE_SIZE);
-/* The maximum write size must be a power of two so it can be used as an
- * emulated maximum page size. */
-BUILD_ASSERT(POWER_OF_TWO(CONFIG_SPI_NOR_MAX_WRITE_SIZE));
-/* Ensure a Serial NOR Flash page program command in 4B addressing mode fits. */
-BUILD_ASSERT(CONFIG_SPI_NOR_MAX_WRITE_SIZE + 5 <=
- CONFIG_SPI_NOR_MAX_MESSAGE_SIZE);
-
-/* A single mutex is used to protect the single buffer, SPI port, and all of the
- * device mutable board defined device states, if the contention is too high it
- * may be worthwhile to change the global mutex granularity to a finer-grained
- * mutex granularity. */
-static struct mutex driver_mutex;
-
-/* Single internal buffer used to stage serial NOR flash commands for the
- * public APIs (read, write, erase). */
-static uint8_t buf[CONFIG_SPI_NOR_MAX_MESSAGE_SIZE];
-
-/******************************************************************************/
-/* Internal driver functions. */
-
-/**
- * Blocking read of the Serial Flash's first status register.
- */
-static int spi_nor_read_status(const struct spi_nor_device_t *spi_nor_device,
- uint8_t *status_register_value)
-{
- uint8_t cmd = SPI_NOR_OPCODE_READ_STATUS;
-
- return spi_transaction(&spi_devices[spi_nor_device->spi_controller],
- &cmd, 1, status_register_value, 1);
-}
-
-/**
- * Set the write enable latch. Device and shared buffer mutexes must be held!
- */
-static int spi_nor_write_enable(const struct spi_nor_device_t *spi_nor_device)
-{
- uint8_t cmd = SPI_NOR_OPCODE_WRITE_ENABLE;
- uint8_t status_register_value;
- int rv = EC_SUCCESS;
-
- /* Set the write enable latch. */
- rv = spi_transaction(&spi_devices[spi_nor_device->spi_controller],
- &cmd, 1, NULL, 0);
- if (rv)
- return rv;
-
- /* Verify the write enabled latch got set. */
- rv = spi_nor_read_status(spi_nor_device, &status_register_value);
- if (rv)
- return rv;
- if ((status_register_value & SPI_NOR_STATUS_REGISTER_WEL) == 0)
- return EC_ERROR_UNKNOWN; /* WEL not set but should be. */
-
- return rv;
-}
-
-/**
- * Read from the extended address register.
- * @param spi_nor_device The Serial NOR Flash device to use.
- * @param value The value to read to.
- * @return ec_error_list (non-zero on error and timeout).
- */
-static int spi_nor_read_ear(const struct spi_nor_device_t *spi_nor_device,
- uint8_t *value)
-{
- uint8_t command = SPI_NOR_OPCODE_RDEAR;
-
- return spi_transaction(&spi_devices[spi_nor_device->spi_controller],
- &command, sizeof(command), value, 1);
-}
-
-int spi_nor_write_ear(const struct spi_nor_device_t *spi_nor_device,
- const uint8_t value)
-{
- uint8_t buf[2];
- int rv;
- uint8_t ear;
-
- mutex_lock(&driver_mutex);
-
- rv = spi_nor_write_enable(spi_nor_device);
- if (rv) {
- CPRINTS(spi_nor_device, "Failed to write enable");
- goto err_free;
- }
-
- buf[0] = SPI_NOR_OPCODE_WREAR;
- buf[1] = value;
-
- rv = spi_transaction(&spi_devices[spi_nor_device->spi_controller],
- buf, sizeof(buf), NULL, 0);
- if (rv) {
- CPRINTS(spi_nor_device, "Failed to write EAR, rv=%d", rv);
- goto err_free;
- }
-
- rv = spi_nor_read_ear(spi_nor_device, &ear);
- if (rv)
- goto err_free;
-
- if (ear != value) {
- CPRINTS(spi_nor_device,
- "Write EAR error: write=%d, read=%d", value, ear);
- rv = EC_ERROR_UNKNOWN; /* WEL not set but should be. */
- goto err_free;
- }
-
-err_free:
- mutex_unlock(&driver_mutex);
- return rv;
-}
-
-/**
- * Block until the Serial NOR Flash clears the BUSY/WIP bit in its status reg.
- */
-static int spi_nor_wait(const struct spi_nor_device_t *spi_nor_device)
-{
- int rv = EC_SUCCESS;
- timestamp_t timeout;
- uint8_t status_register_value;
-
- rv = spi_nor_read_status(spi_nor_device, &status_register_value);
- if (rv)
- return rv;
- timeout.val =
- get_time().val + spi_nor_device->timeout_usec;
- while (status_register_value & SPI_NOR_STATUS_REGISTER_WIP) {
- /* Reload the watchdog before sleeping. */
- watchdog_reload();
- usleep(SPI_NOR_WIP_SLEEP_USEC);
-
- /* Give up if the deadline has been exceeded. */
- if (get_time().val > timeout.val)
- return EC_ERROR_TIMEOUT;
-
- /* Re-read the status register. */
- rv = spi_nor_read_status(spi_nor_device,
- &status_register_value);
- if (rv)
- return rv;
- }
-
- return rv;
-}
-
-/**
- * Read the Manufacturer bank and ID out of the JEDEC ID.
- */
-static int spi_nor_read_jedec_mfn_id(
- const struct spi_nor_device_t *spi_nor_device,
- uint8_t *out_mfn_bank,
- uint8_t *out_mfn_id)
-{
- int rv = EC_SUCCESS;
- uint8_t jedec_id[SPI_NOR_JEDEC_ID_BANKS];
- size_t i;
- uint8_t cmd = SPI_NOR_OPCODE_JEDEC_ID;
-
- /* Read the standardized part of the JEDEC ID. */
- rv = spi_transaction(&spi_devices[spi_nor_device->spi_controller],
- &cmd, 1, jedec_id, SPI_NOR_JEDEC_ID_BANKS);
- if (rv)
- return rv;
-
- *out_mfn_bank = 0;
- /* Go through the JEDEC ID a byte a time to looking for a manufacturer
- * ID instead of the next bank indicator (0x7F). */
- for (i = 0; i < SPI_NOR_JEDEC_ID_BANKS; i++) {
- *out_mfn_id = jedec_id[i];
- if (*out_mfn_id != 0x7F)
- return EC_SUCCESS;
- *out_mfn_bank += 1;
- }
- /* JEDEC Manufacturer ID should be available, perhaps there is a bus
- * problem or the JEP106 specification has grown the number of banks? */
- return EC_ERROR_UNKNOWN;
-}
-
-/**
- * Read a doubleword out of a SFDP table (DWs are 1-based like the SFDP spec).
- */
-static int spi_nor_read_sfdp_dword(
- const struct spi_nor_device_t *spi_nor_device,
- uint32_t table_offset,
- uint8_t table_double_word,
- uint32_t *out_dw) {
- uint8_t sfdp_cmd[5];
- /* Calculate the byte offset based on the double word. */
- uint32_t sfdp_offset = table_offset + ((table_double_word - 1) * 4);
-
- /* Read the DW out of the SFDP region. */
- sfdp_cmd[0] = SPI_NOR_OPCODE_SFDP;
- sfdp_cmd[1] = (sfdp_offset & 0xFF0000) >> 16;
- sfdp_cmd[2] = (sfdp_offset & 0xFF00) >> 8;
- sfdp_cmd[3] = (sfdp_offset & 0xFF);
- sfdp_cmd[4] = 0; /* Required extra cycle. */
- return spi_transaction(&spi_devices[spi_nor_device->spi_controller],
- sfdp_cmd, 5, (uint8_t *)out_dw, 4);
-}
-
-/**
- * Returns a bool (1 or 0) based on whether the parameter header double words
- * are for a SFDP v1.* Basic SPI Flash NOR Parameter Table.
- */
-static int is_basic_flash_parameter_table(uint8_t sfdp_major_rev,
- uint8_t sfdp_minor_rev,
- uint32_t parameter_header_dw1,
- uint32_t parameter_header_dw2)
-{
- if (sfdp_major_rev == 1 && sfdp_minor_rev < 5) {
- return (SFDP_GET_BITFIELD(SFDP_1_0_PARAMETER_HEADER_DW1_ID,
- parameter_header_dw1) ==
- BASIC_FLASH_PARAMETER_TABLE_1_0_ID);
- } else if (sfdp_major_rev == 1 && sfdp_minor_rev >= 5) {
- return ((SFDP_GET_BITFIELD(SFDP_1_5_PARAMETER_HEADER_DW1_ID_LSB,
- parameter_header_dw1) ==
- BASIC_FLASH_PARAMETER_TABLE_1_5_ID_LSB) &&
- (SFDP_GET_BITFIELD(SFDP_1_5_PARAMETER_HEADER_DW2_ID_MSB,
- parameter_header_dw2) ==
- BASIC_FLASH_PARAMETER_TABLE_1_5_ID_MSB));
- }
-
- return 0;
-}
-
-/**
- * Helper function to locate the SFDP Basic SPI Flash NOR Parameter Table.
- */
-static int locate_sfdp_basic_parameter_table(
- const struct spi_nor_device_t *spi_nor_device,
- uint8_t *out_sfdp_major_rev,
- uint8_t *out_sfdp_minor_rev,
- uint8_t *out_table_major_rev,
- uint8_t *out_table_minor_rev,
- uint32_t *out_table_offset,
- size_t *out_table_size)
-{
- int rv = EC_SUCCESS;
- uint8_t number_parameter_headers;
- uint32_t table_offset = 0;
- int table_found = 0;
- uint32_t dw1;
- uint32_t dw2;
-
- /* Read the SFDP header. */
- rv = spi_nor_read_sfdp_dword(spi_nor_device, 0, 1, &dw1);
- rv |= spi_nor_read_sfdp_dword(spi_nor_device, 0, 2, &dw2);
- if (rv)
- return rv;
-
- /* Ensure the SFDP table is valid. Note the versions are not checked
- * through the SFDP table header, as there may be a backwards
- * compatible, older basic parameter tables which are compatible with
- * this driver in the parameter headers. */
- if (!SFDP_HEADER_DW1_SFDP_SIGNATURE_VALID(dw1)) {
- CPRINTS(spi_nor_device, "SFDP signature invalid");
- return EC_ERROR_UNKNOWN;
- }
-
- *out_sfdp_major_rev =
- SFDP_GET_BITFIELD(SFDP_HEADER_DW2_SFDP_MAJOR, dw2);
- *out_sfdp_minor_rev =
- SFDP_GET_BITFIELD(SFDP_HEADER_DW2_SFDP_MINOR, dw2);
- CPRINTS(spi_nor_device, "SFDP v%d.%d discovered",
- *out_sfdp_major_rev, *out_sfdp_minor_rev);
-
- /* NPH is 0-based, so add 1. */
- number_parameter_headers =
- SFDP_GET_BITFIELD(SFDP_HEADER_DW2_NPH, dw2) + 1;
- CPRINTS(spi_nor_device, "There are %d SFDP parameter headers",
- number_parameter_headers);
-
- /* Search for the newest, compatible basic flash parameter table. */
- *out_table_major_rev = 0;
- *out_table_minor_rev = 0;
- while (number_parameter_headers) {
- uint8_t major_rev, minor_rev;
-
- table_offset += 8;
- number_parameter_headers--;
-
- /* Read this parameter header's two dwords. */
- rv = spi_nor_read_sfdp_dword(
- spi_nor_device, table_offset, 1, &dw1);
- rv |= spi_nor_read_sfdp_dword(
- spi_nor_device, table_offset, 2, &dw2);
- if (rv)
- return rv;
-
- /* Ensure it's the basic flash parameter table. */
- if (!is_basic_flash_parameter_table(*out_sfdp_major_rev,
- *out_sfdp_minor_rev,
- dw1, dw2))
- continue;
-
- /* The parameter header major and minor versioning is still the
- * same as SFDP 1.0. */
- major_rev = SFDP_GET_BITFIELD(
- SFDP_1_0_PARAMETER_HEADER_DW1_TABLE_MAJOR, dw1);
- minor_rev = SFDP_GET_BITFIELD(
- SFDP_1_0_PARAMETER_HEADER_DW1_TABLE_MINOR, dw1);
-
- /* Skip incompatible parameter tables. */
- if (major_rev != SPI_NOR_SUPPORTED_SFDP_MAJOR_VERSION)
- continue;
-
- /* If this parameter table has a lower revision compared to a
- * previously found compatible table, skip it. */
- if (minor_rev < *out_table_minor_rev)
- continue;
-
- table_found = 1;
- *out_table_major_rev = major_rev;
- *out_table_minor_rev = minor_rev;
- /* The parameter header ptp and ptl are still the same as
- * SFDP 1.0. */
- *out_table_offset = SFDP_GET_BITFIELD(
- SFDP_1_0_PARAMETER_HEADER_DW2_PTP, dw2);
- /* Convert the size from DW to Bytes. */
- *out_table_size = SFDP_GET_BITFIELD(
- SFDP_1_0_PARAMETER_HEADER_DW1_PTL, dw1) * 4;
- }
-
- if (!table_found) {
- CPRINTS(spi_nor_device,
- "No compatible Basic Flash Parameter Table found");
- return EC_ERROR_UNKNOWN;
- }
-
- CPRINTS(spi_nor_device, "Using Basic Flash Parameter Table v%d.%d",
- *out_sfdp_major_rev, *out_sfdp_minor_rev);
-
- return EC_SUCCESS;
-}
-
-/**
- * Helper function to lookup the part's page size in the SFDP Basic SPI Flash
- * NOR Parameter Table.
- */
-static int spi_nor_device_discover_sfdp_page_size(
- struct spi_nor_device_t *spi_nor_device,
- uint8_t basic_parameter_table_major_version,
- uint8_t basic_parameter_table_minor_version,
- uint32_t basic_parameter_table_offset,
- size_t *page_size)
-{
- int rv = EC_SUCCESS;
- uint32_t dw;
-
- if (basic_parameter_table_major_version == 1 &&
- basic_parameter_table_minor_version < 5) {
- /* Use the Basic Flash Parameter v1.0 page size reporting. */
- rv = spi_nor_read_sfdp_dword(
- spi_nor_device, basic_parameter_table_offset, 1, &dw);
- if (rv)
- return rv;
- if (SFDP_GET_BITFIELD(BFPT_1_0_DW1_WRITE_GRANULARITY, dw))
- *page_size = 64;
- else
- *page_size = 1;
-
- } else if (basic_parameter_table_major_version == 1 &&
- basic_parameter_table_minor_version >= 5) {
- /* Use the Basic Flash Parameter v1.5 page size reporting. */
- rv = spi_nor_read_sfdp_dword(spi_nor_device,
- basic_parameter_table_offset, 11, &dw);
- if (rv)
- return rv;
- *page_size =
- 1 << SFDP_GET_BITFIELD(BFPT_1_5_DW11_PAGE_SIZE, dw);
- }
-
- return EC_SUCCESS;
-}
-
-/**
- * Helper function to lookup the part's capacity in the SFDP Basic SPI Flash
- * NOR Parameter Table.
- */
-static int spi_nor_device_discover_sfdp_capacity(
- struct spi_nor_device_t *spi_nor_device,
- uint8_t basic_parameter_table_major_version,
- uint8_t basic_parameter_table_minor_version,
- uint32_t basic_parameter_table_offset,
- uint32_t *capacity)
-{
- int rv = EC_SUCCESS;
- uint32_t dw;
-
- /* First attempt to discover the device's capacity. */
- if (basic_parameter_table_major_version == 1) {
- /* Use the Basic Flash Parameter v1.0 capacity reporting. */
- rv = spi_nor_read_sfdp_dword(spi_nor_device,
- basic_parameter_table_offset, 2, &dw);
- if (rv)
- return rv;
-
- if (SFDP_GET_BITFIELD(BFPT_1_0_DW2_GT_2_GIBIBITS, dw)) {
- /* Ensure the capacity is less than 4GiB. */
- uint64_t tmp_capacity = 1 <<
- (SFDP_GET_BITFIELD(BFPT_1_0_DW2_N, dw) - 3);
- if (tmp_capacity > UINT32_MAX)
- return EC_ERROR_OVERFLOW;
- *capacity = tmp_capacity;
- } else {
- *capacity =
- 1 +
- (SFDP_GET_BITFIELD(BFPT_1_0_DW2_N, dw) >> 3);
- }
- }
-
- return EC_SUCCESS;
-}
-
-static int spi_nor_read_internal(const struct spi_nor_device_t *spi_nor_device,
- uint32_t offset, size_t size, uint8_t *data)
-{
- int rv;
-
- /* Split up the read operation into multiple transactions if the size
- * is larger than the maximum read size.
- */
- while (size > 0) {
- size_t read_size =
- MIN(size, CONFIG_SPI_NOR_MAX_READ_SIZE);
- size_t read_command_size;
-
- /* Set up the read command in the TX buffer. */
- buf[0] = SPI_NOR_OPCODE_SLOW_READ;
- if (spi_nor_device->in_4b_addressing_mode) {
- buf[1] = (offset & 0xFF000000) >> 24;
- buf[2] = (offset & 0xFF0000) >> 16;
- buf[3] = (offset & 0xFF00) >> 8;
- buf[4] = (offset & 0xFF);
- read_command_size = 5;
- } else { /* in 3 byte addressing mode */
- buf[1] = (offset & 0xFF0000) >> 16;
- buf[2] = (offset & 0xFF00) >> 8;
- buf[3] = (offset & 0xFF);
- read_command_size = 4;
- }
-
- rv = spi_transaction(
- &spi_devices[spi_nor_device->spi_controller],
- buf, read_command_size, data, read_size);
- if (rv)
- return rv;
-
- data += read_size;
- offset += read_size;
- size -= read_size;
- }
- return EC_SUCCESS;
-}
-
-/******************************************************************************/
-/* External Serial NOR Flash API available to other modules. */
-
-/**
- * Initialize the module, assumes the Serial NOR Flash devices are currently
- * all available for initialization. As part of the initialization the driver
- * will check if the part has a compatible SFDP Basic Flash Parameter table
- * and update the part's page_size, capacity, and forces the addressing mode.
- * Parts with more than 16MiB of capacity are initialized into 4B addressing
- * and parts with less are initialized into 3B addressing mode.
- *
- * WARNING: This must successfully return before invoking any other Serial NOR
- * Flash APIs.
- */
-int spi_nor_init(void)
-{
- int rv = EC_SUCCESS;
- size_t i;
-
- /* Initialize the state for each serial NOR flash device. */
- for (i = 0; i < SPI_NOR_DEVICE_COUNT; i++) {
- uint8_t sfdp_major_rev, sfdp_minor_rev;
- uint8_t table_major_rev, table_minor_rev;
- uint32_t table_offset;
- size_t table_size;
- struct spi_nor_device_t *spi_nor_device =
- &spi_nor_devices[i];
-
- rv |= locate_sfdp_basic_parameter_table(spi_nor_device,
- &sfdp_major_rev,
- &sfdp_minor_rev,
- &table_major_rev,
- &table_minor_rev,
- &table_offset,
- &table_size);
-
- /* If we failed to find a compatible SFDP Basic Flash Parameter
- * table, use the default capacity, page size, and addressing
- * mode values. */
- if (rv == EC_SUCCESS) {
- size_t page_size = 0;
- uint32_t capacity = 0;
-
- rv |= spi_nor_device_discover_sfdp_page_size(
- spi_nor_device,
- table_major_rev, table_minor_rev, table_offset,
- &page_size);
- rv |= spi_nor_device_discover_sfdp_capacity(
- spi_nor_device,
- table_major_rev, table_minor_rev, table_offset,
- &capacity);
- if (rv == EC_SUCCESS) {
- mutex_lock(&driver_mutex);
- spi_nor_device->capacity = capacity;
- spi_nor_device->page_size = page_size;
- CPRINTS(spi_nor_device,
- "Updated to SFDP params: %dKiB w/ %dB pages",
- spi_nor_device->capacity >> 10,
- spi_nor_device->page_size);
- mutex_unlock(&driver_mutex);
- }
- }
-
- /* Ensure the device is in a determined addressing state by
- * forcing a 4B addressing mode entry or exit depending on the
- * device capacity. If the device is larger than 16MiB, enter
- * 4B addressing mode. */
- rv |= spi_nor_set_4b_mode(spi_nor_device,
- spi_nor_device->capacity > 0x1000000);
- }
-
- return rv;
-}
-
-/**
- * Forces the Serial NOR Flash device to enter (or exit) 4 Byte addressing mode.
- *
- * WARNING:
- * 1) In 3 Byte addressing mode only 16MiB of Serial NOR Flash is accessible.
- * 2) If there's a second SPI controller communicating with this Serial
- * NOR Flash part on the board, the user is responsible for ensuring
- * addressing mode compatibility and cooperation.
- * 3) The user must ensure that multiple users do not trample on each other
- * by having multiple parties changing the device's addressing mode.
- *
- * @param spi_nor_device The Serial NOR Flash device to use.
- * @param enter_4b_addressing_mode Whether to enter (1) or exit (0) 4B mode.
- * @return ec_error_list (non-zero on error and timeout).
- */
-int spi_nor_set_4b_mode(struct spi_nor_device_t *spi_nor_device,
- int enter_4b_addressing_mode)
-{
- uint8_t cmd;
- int rv;
-
- rv = spi_nor_write_enable(spi_nor_device);
- if (rv)
- return rv;
-
- if (enter_4b_addressing_mode)
- cmd = SPI_NOR_DRIVER_SPECIFIED_OPCODE_ENTER_4B;
- else
- cmd = SPI_NOR_DRIVER_SPECIFIED_OPCODE_EXIT_4B;
-
- /* Claim the driver mutex to modify the device state. */
- mutex_lock(&driver_mutex);
-
- rv = spi_transaction(&spi_devices[spi_nor_device->spi_controller],
- &cmd, 1, NULL, 0);
- if (rv == EC_SUCCESS) {
- spi_nor_device->in_4b_addressing_mode =
- enter_4b_addressing_mode;
- }
-
- CPRINTS(spi_nor_device, "Entered %s Addressing Mode",
- enter_4b_addressing_mode ? "4-Byte" : "3-Byte");
-
- /* Release the driver mutex. */
- mutex_unlock(&driver_mutex);
- return rv;
-}
-
-/**
- * Read JEDEC Identifier.
- *
- * @param spi_nor_device The Serial NOR Flash device to use.
- * @param size Number of Bytes to read.
- * @param data Destination buffer for data.
- * @return ec_error_list (non-zero on error and timeout).
- */
-int spi_nor_read_jedec_id(const struct spi_nor_device_t *spi_nor_device,
- size_t size, uint8_t *data) {
- int rv;
- uint8_t cmd = SPI_NOR_OPCODE_JEDEC_ID;
-
- if (size > CONFIG_SPI_NOR_MAX_READ_SIZE)
- return EC_ERROR_INVAL;
- /* Claim the driver mutex. */
- mutex_lock(&driver_mutex);
- /* Read the JEDEC ID. */
- rv = spi_transaction(&spi_devices[spi_nor_device->spi_controller],
- &cmd, 1, data, size);
- /* Release the driver mutex. */
- mutex_unlock(&driver_mutex);
-
- return rv;
-}
-
-/**
- * Read from the Serial NOR Flash device.
- *
- * @param spi_nor_device The Serial NOR Flash device to use.
- * @param offset Flash offset to read.
- * @param size Number of Bytes to read.
- * @param data Destination buffer for data.
- * @return ec_error_list (non-zero on error and timeout).
- */
-int spi_nor_read(const struct spi_nor_device_t *spi_nor_device,
- uint32_t offset, size_t size, uint8_t *data)
-{
- int rv;
-
- /* Claim the driver mutex. */
- mutex_lock(&driver_mutex);
- rv = spi_nor_read_internal(spi_nor_device, offset, size, data);
- /* Release the driver mutex. */
- mutex_unlock(&driver_mutex);
-
- return rv;
-}
-
-/**
- * Erase flash on the Serial Flash Device.
- *
- * @param spi_nor_device The Serial NOR Flash device to use.
- * @param offset Flash offset to erase, must be aligned to the minimum physical
- * erase size.
- * @param size Number of Bytes to erase, must be a multiple of the the minimum
- * physical erase size.
- * @return ec_error_list (non-zero on error and timeout).
- */
-int spi_nor_erase(const struct spi_nor_device_t *spi_nor_device,
- uint32_t offset, size_t size)
-{
- int rv = EC_SUCCESS;
- size_t erase_command_size, erase_size;
- uint8_t erase_opcode;
-#ifdef CONFIG_SPI_NOR_SMART_ERASE
- BUILD_ASSERT((CONFIG_SPI_NOR_MAX_READ_SIZE % 4) == 0);
- uint8_t buffer[CONFIG_SPI_NOR_MAX_READ_SIZE] __aligned(4);
- size_t verify_offset, read_offset, read_size, read_left;
-#endif
-
- /* Invalid input */
- if ((offset % 4096 != 0) || (size % 4096 != 0) || (size < 4096))
- return EC_ERROR_INVAL;
-
- /* Claim the driver mutex. */
- mutex_lock(&driver_mutex);
-
- while (size > 0) {
- erase_opcode = SPI_NOR_DRIVER_SPECIFIED_OPCODE_4KIB_ERASE;
- erase_size = 4096;
-
- /* Wait for the previous operation to finish. */
- rv = spi_nor_wait(spi_nor_device);
- if (rv)
- goto err_free;
-
-#ifdef CONFIG_SPI_NOR_BLOCK_ERASE
- if (!(offset % 65536) && size >= 65536) {
- erase_opcode =
- SPI_NOR_DRIVER_SPECIFIED_OPCODE_64KIB_ERASE;
- erase_size = 65536;
- }
-#endif
-#ifdef CONFIG_SPI_NOR_SMART_ERASE
- read_offset = offset;
- read_left = erase_size;
- while (read_left) {
- read_size = MIN(read_left,
- CONFIG_SPI_NOR_MAX_READ_SIZE);
- /* Since CONFIG_SPI_NOR_MAX_READ_SIZE & erase_size are
- * both guaranteed to be multiples of 4.
- */
- assert(read_size >= 4 && (read_size % 4) == 0);
- rv = spi_nor_read_internal(spi_nor_device, read_offset,
- read_size, buffer);
-
- /* Note: the return value here is lost below
- * at the write enable, this is not a problem,
- * as this code is only an optimisation, if it
- * fails, the full erase functionality still
- * gets done, and the error from that returned
- */
- if (rv != EC_SUCCESS)
- break;
- /* Aligned word verify reduced the overall (read +
- * verify) time by ~20% (vs bytewise verify) on
- * an m3@24MHz & SPI@24MHz.
- */
- verify_offset = 0;
- while (verify_offset <= read_size - 4) {
- if (*(uint32_t *)(buffer + verify_offset)
- != 0xffffffff) {
- break;
- }
- verify_offset += 4;
- }
- if (verify_offset != read_size)
- break;
- read_offset += read_size;
- read_left -= read_size;
- watchdog_reload();
- }
- if (!read_left) {
- /* Sector/block already erased. */
- CPRINTS(spi_nor_device,
- "Skipping erase [%x:%x] "
- "(already erased)",
- offset, erase_size);
- offset += erase_size;
- size -= erase_size;
- continue;
- }
-#endif
- /* Enable writing to serial NOR flash. */
- rv = spi_nor_write_enable(spi_nor_device);
- if (rv)
- goto err_free;
-
- /* Set up the erase instruction. */
- buf[0] = erase_opcode;
- if (spi_nor_device->in_4b_addressing_mode) {
- buf[1] = (offset & 0xFF000000) >> 24;
- buf[2] = (offset & 0xFF0000) >> 16;
- buf[3] = (offset & 0xFF00) >> 8;
- buf[4] = (offset & 0xFF);
- erase_command_size = 5;
- } else { /* in 3 byte addressing mode */
- buf[1] = (offset & 0xFF0000) >> 16;
- buf[2] = (offset & 0xFF00) >> 8;
- buf[3] = (offset & 0xFF);
- erase_command_size = 4;
- }
-
- rv = spi_transaction(
- &spi_devices[spi_nor_device->spi_controller],
- buf, erase_command_size, NULL, 0);
- if (rv)
- goto err_free;
-
- offset += erase_size;
- size -= erase_size;
- }
-
- /* Wait for the previous operation to finish. */
- rv = spi_nor_wait(spi_nor_device);
-
-err_free:
- /* Release the driver mutex. */
- mutex_unlock(&driver_mutex);
-
- return rv;
-}
-
-/**
- * Write to the Serial NOR Flash device. Assumes already erased.
- *
- * @param spi_nor_device The Serial NOR Flash device to use.
- * @param offset Flash offset to write.
- * @param size Number of Bytes to write.
- * @param data Data to write to flash.
- * @return ec_error_list (non-zero on error and timeout).
- */
-int spi_nor_write(const struct spi_nor_device_t *spi_nor_device,
- uint32_t offset, size_t size, const uint8_t *data)
-{
- int rv = EC_SUCCESS;
- size_t effective_page_size;
-
- /* Claim the driver mutex. */
- mutex_lock(&driver_mutex);
-
- /* Ensure the device's page size fits in the driver's buffer, if not
- * emulate a smaller page size based on the buffer size. */
- effective_page_size = MIN(spi_nor_device->page_size,
- CONFIG_SPI_NOR_MAX_WRITE_SIZE);
-
- /* Split the write into multiple writes if the size is too large. */
- while (size > 0) {
- size_t prefix_size;
- /* Figure out the size of the next write within 1 page. */
- uint32_t page_offset = offset & (effective_page_size - 1);
- size_t write_size =
- MIN(size, effective_page_size - page_offset);
-
- /* Wait for the previous operation to finish. */
- rv = spi_nor_wait(spi_nor_device);
- if (rv)
- goto err_free;
-
- /* Enable writing to serial NOR flash. */
- rv = spi_nor_write_enable(spi_nor_device);
- if (rv)
- goto err_free;
-
- /* Set up the page program command. */
- buf[0] = SPI_NOR_OPCODE_PAGE_PROGRAM;
- if (spi_nor_device->in_4b_addressing_mode) {
- buf[1] = (offset & 0xFF000000) >> 24;
- buf[2] = (offset & 0xFF0000) >> 16;
- buf[3] = (offset & 0xFF00) >> 8;
- buf[4] = (offset & 0xFF);
- prefix_size = 5;
- } else { /* in 3 byte addressing mode */
- buf[1] = (offset & 0xFF0000) >> 16;
- buf[2] = (offset & 0xFF00) >> 8;
- buf[3] = (offset & 0xFF);
- prefix_size = 4;
- }
- /* Copy data to write into the buffer after the prefix. */
- memmove(buf + prefix_size, data, write_size);
-
- rv = spi_transaction(
- &spi_devices[spi_nor_device->spi_controller],
- buf, prefix_size + write_size, NULL, 0);
- if (rv)
- goto err_free;
-
- data += write_size;
- offset += write_size;
- size -= write_size;
- }
-
- /* Wait for the previous operation to finish. */
- rv = spi_nor_wait(spi_nor_device);
-
-err_free:
- /* Release the driver mutex. */
- mutex_unlock(&driver_mutex);
-
- return rv;
-}
-
-/******************************************************************************/
-/* Serial NOR Flash console commands. */
-
-#ifdef CONFIG_CMD_SPI_NOR
-static int command_spi_nor_info(int argc, char **argv)
-{
- int rv = EC_SUCCESS;
-
- uint8_t sfdp_major_rev, sfdp_minor_rev;
- uint8_t table_major_rev, table_minor_rev;
- uint32_t table_offset;
- uint8_t mfn_bank = 0, mfn_id = 0;
- size_t table_size;
- const struct spi_nor_device_t *spi_nor_device = 0;
- int spi_nor_device_index = 0;
- int spi_nor_device_index_limit = spi_nor_devices_used - 1;
-
- /* Set the device index limits if a device was specified. */
- if (argc == 2) {
- spi_nor_device_index = strtoi(argv[1], NULL, 0);
- if (spi_nor_device_index >= spi_nor_devices_used)
- return EC_ERROR_PARAM1;
- spi_nor_device_index_limit = spi_nor_device_index;
- } else if (argc != 1) {
- return EC_ERROR_PARAM_COUNT;
- }
-
- for (; spi_nor_device_index <= spi_nor_device_index_limit;
- spi_nor_device_index++) {
- spi_nor_device = &spi_nor_devices[spi_nor_device_index];
-
- ccprintf("Serial NOR Flash Device %d:\n", spi_nor_device_index);
- ccprintf("\tName: %s\n", spi_nor_device->name);
- ccprintf("\tSPI controller index: %d\n",
- spi_nor_device->spi_controller);
- ccprintf("\tTimeout: %d uSec\n",
- spi_nor_device->timeout_usec);
- ccprintf("\tCapacity: %d KiB\n",
- spi_nor_device->capacity >> 10),
- ccprintf("\tAddressing: %s addressing mode\n",
- spi_nor_device->in_4b_addressing_mode ? "4B" : "3B");
- ccprintf("\tPage Size: %d Bytes\n",
- spi_nor_device->page_size);
-
- /* Get JEDEC ID info. */
- rv = spi_nor_read_jedec_mfn_id(spi_nor_device, &mfn_bank,
- &mfn_id);
- if (rv != EC_SUCCESS)
- return rv;
- ccprintf("\tJEDEC ID bank %d manufacturing code 0x%x\n",
- mfn_bank, mfn_id);
-
- /* Get SFDP info. */
- if (locate_sfdp_basic_parameter_table(
- spi_nor_device, &sfdp_major_rev, &sfdp_minor_rev,
- &table_major_rev, &table_minor_rev, &table_offset,
- &table_size) != EC_SUCCESS) {
- ccputs("\tNo JEDEC SFDP support detected\n");
- continue; /* Go on to the next device. */
- }
- ccprintf("\tSFDP v%d.%d\n", sfdp_major_rev, sfdp_minor_rev);
- ccprintf("\tFlash Parameter Table v%d.%d (%dB @ 0x%x)\n",
- table_major_rev, table_minor_rev,
- table_size, table_offset);
- }
-
- return rv;
-}
-DECLARE_CONSOLE_COMMAND(spinorinfo, command_spi_nor_info,
- "[device]",
- "Report Serial NOR Flash device information");
-#endif /* CONFIG_CMD_SPI_NOR */
-
-#ifdef CONFIG_CMD_SPI_NOR
-static int command_spi_nor_erase(int argc, char **argv)
-{
- const struct spi_nor_device_t *spi_nor_device;
- int spi_nor_device_index;
- int offset = 0;
- int size = 4096;
- int rv;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- spi_nor_device_index = strtoi(argv[1], NULL, 0);
- if (spi_nor_device_index >= spi_nor_devices_used)
- return EC_ERROR_PARAM1;
- spi_nor_device = &spi_nor_devices[spi_nor_device_index];
-
- rv = parse_offset_size(argc, argv, 2, &offset, &size);
- if (rv)
- return rv;
-
- ccprintf("Erasing %d bytes at 0x%x on %s...\n",
- size, offset, spi_nor_device->name);
- return spi_nor_erase(spi_nor_device, offset, size);
-}
-DECLARE_CONSOLE_COMMAND(spinorerase, command_spi_nor_erase,
- "device [offset] [size]",
- "Erase flash");
-#endif /* CONFIG_CMD_SPI_NOR */
-
-#ifdef CONFIG_CMD_SPI_NOR
-static int command_spi_nor_write(int argc, char **argv)
-{
- const struct spi_nor_device_t *spi_nor_device;
- int spi_nor_device_index;
- int offset = 0;
- int size = CONFIG_SPI_NOR_MAX_WRITE_SIZE;
- int rv;
- char *data;
- int i;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- spi_nor_device_index = strtoi(argv[1], NULL, 0);
- if (spi_nor_device_index >= spi_nor_devices_used)
- return EC_ERROR_PARAM1;
- spi_nor_device = &spi_nor_devices[spi_nor_device_index];
-
- rv = parse_offset_size(argc, argv, 2, &offset, &size);
- if (rv)
- return rv;
-
- if (size > shared_mem_size())
- size = shared_mem_size();
-
- /* Acquire the shared memory buffer */
- rv = shared_mem_acquire(size, &data);
- if (rv) {
- ccputs("Can't get shared mem\n");
- return rv;
- }
-
- /* Fill the data buffer with a pattern */
- for (i = 0; i < size; i++)
- data[i] = i;
-
- ccprintf("Writing %d bytes to 0x%x on %s...\n",
- size, offset, spi_nor_device->name);
- rv = spi_nor_write(spi_nor_device, offset, size, data);
-
- /* Free the buffer */
- shared_mem_release(data);
-
- return rv;
-}
-DECLARE_CONSOLE_COMMAND(spinorwrite, command_spi_nor_write,
- "device [offset] [size]",
- "Write pattern to flash");
-#endif /* CONFIG_CMD_SPI_NOR */
-
-#ifdef CONFIG_CMD_SPI_NOR
-static int command_spi_nor_read(int argc, char **argv)
-{
- const struct spi_nor_device_t *spi_nor_device;
- int spi_nor_device_index;
- int offset = 0;
- int size = CONFIG_SPI_NOR_MAX_READ_SIZE;
- int rv;
- char *data;
- int i;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- spi_nor_device_index = strtoi(argv[1], NULL, 0);
- if (spi_nor_device_index >= spi_nor_devices_used)
- return EC_ERROR_PARAM1;
- spi_nor_device = &spi_nor_devices[spi_nor_device_index];
-
- rv = parse_offset_size(argc, argv, 2, &offset, &size);
- if (rv)
- return rv;
-
- if (size > shared_mem_size())
- size = shared_mem_size();
-
- /* Acquire the shared memory buffer */
- rv = shared_mem_acquire(size, &data);
- if (rv) {
- ccputs("Can't get shared mem\n");
- return rv;
- }
-
- /* Read the data */
- ccprintf("Reading %d bytes from %s...",
- size, spi_nor_device->name);
- if (spi_nor_read(spi_nor_device, offset, size, data)) {
- rv = EC_ERROR_INVAL;
- goto err_free;
- }
-
- /* Dump it */
- for (i = 0; i < size; i++) {
- if ((offset + i) % 16) {
- ccprintf(" %02x", data[i]);
- } else {
- ccprintf("\n%08x: %02x", offset + i, data[i]);
- cflush();
- }
- }
- ccprintf("\n");
-
-err_free:
- /* Free the buffer */
- shared_mem_release(data);
-
- return rv;
-}
-DECLARE_CONSOLE_COMMAND(spinorread, command_spi_nor_read,
- "device [offset] [size]",
- "Read flash");
-#endif /* CONFIG_CMD_SPI_NOR */
diff --git a/common/stillness_detector.c b/common/stillness_detector.c
deleted file mode 100644
index c33472aa22..0000000000
--- a/common/stillness_detector.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/* Copyright 2019 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.
- */
-
-#include "common.h"
-#include "stillness_detector.h"
-#include "timer.h"
-#include <string.h>
-
-static void still_det_reset(struct still_det *still_det)
-{
- still_det->num_samples = 0;
- still_det->acc_x = FLOAT_TO_FP(0.0f);
- still_det->acc_y = FLOAT_TO_FP(0.0f);
- still_det->acc_z = FLOAT_TO_FP(0.0f);
- still_det->acc_xx = FLOAT_TO_FP(0.0f);
- still_det->acc_yy = FLOAT_TO_FP(0.0f);
- still_det->acc_zz = FLOAT_TO_FP(0.0f);
-}
-
-static bool stillness_batch_complete(struct still_det *still_det,
- uint32_t sample_time)
-{
- bool complete = false;
- uint32_t batch_window = time_until(still_det->window_start_time,
- sample_time);
-
- /* Checking if enough data is accumulated */
- if (batch_window >= still_det->min_batch_window &&
- still_det->num_samples > still_det->min_batch_size) {
- if (batch_window <= still_det->max_batch_window) {
- complete = true;
- } else {
- /* Checking for too long batch window, reset and start
- * over
- */
- still_det_reset(still_det);
- }
- } else if (batch_window > still_det->min_batch_window &&
- still_det->num_samples < still_det->min_batch_size) {
- /* Not enough samples collected, reset and start over */
- still_det_reset(still_det);
- }
- return complete;
-}
-
-static inline fp_t compute_variance(fp_t acc_squared, fp_t acc, fp_t inv)
-{
- /* (acc^2 - (acc * acc * inv)) * inv */
- return fp_mul((acc_squared - fp_mul(fp_sq(acc), inv)), inv);
-}
-
-bool still_det_update(struct still_det *still_det, uint32_t sample_time,
- fp_t x, fp_t y, fp_t z)
-{
- fp_t inv = FLOAT_TO_FP(0.0f), var_x, var_y, var_z;
- bool complete = false;
-
- /* Accumulate for mean and VAR */
- still_det->acc_x += x;
- still_det->acc_y += y;
- still_det->acc_z += z;
- still_det->acc_xx += fp_mul(x, x);
- still_det->acc_yy += fp_mul(y, y);
- still_det->acc_zz += fp_mul(z, z);
-
- switch (++still_det->num_samples) {
- case 0:
- /* If we rolled over, go back. */
- still_det->num_samples--;
- break;
- case 1:
- /* Set a new start time if new batch. */
- still_det->window_start_time = sample_time;
- break;
- }
-
- if (stillness_batch_complete(still_det, sample_time)) {
- /*
- * Compute 1/num_samples and check for num_samples == 0 (should
- * never happen, but just in case)
- */
- if (still_det->num_samples) {
- inv = fp_div(1.0f, INT_TO_FP(still_det->num_samples));
- } else {
- still_det_reset(still_det);
- return complete;
- }
- /* Calculating the VAR = sum(x^2)/n - sum(x)^2/n^2 */
- var_x = compute_variance(
- still_det->acc_xx, still_det->acc_x, inv);
- var_y = compute_variance(
- still_det->acc_yy, still_det->acc_y, inv);
- var_z = compute_variance(
- still_det->acc_zz, still_det->acc_z, inv);
- /* Checking if sensor is still */
- if (var_x < still_det->var_threshold &&
- var_y < still_det->var_threshold &&
- var_z < still_det->var_threshold) {
- still_det->mean_x = fp_mul(still_det->acc_x, inv);
- still_det->mean_y = fp_mul(still_det->acc_y, inv);
- still_det->mean_z = fp_mul(still_det->acc_z, inv);
- complete = true;
- }
- /* Reset and start over */
- still_det_reset(still_det);
- }
- return complete;
-}
diff --git a/common/switch.c b/common/switch.c
deleted file mode 100644
index 2c1ea804a8..0000000000
--- a/common/switch.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* Copyright 2013 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.
- */
-
-/* Switch module for Chrome EC */
-
-#include "common.h"
-#include "console.h"
-#include "flash.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "lid_switch.h"
-#include "power_button.h"
-#include "switch.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_SWITCH, outstr)
-#define CPRINTS(format, args...) cprints(CC_SWITCH, format, ## args)
-
-static uint8_t *memmap_switches;
-
-/**
- * Update status of non-debounced switches.
- *
- * Note that deferred functions are called in the same context as lid and
- * power button changes, so we don't need a mutex.
- */
-static void switch_update(void)
-{
- static uint8_t prev;
-
- /* Make sure this is safe to call before power_button_init() */
- if (!memmap_switches)
- return;
-
- prev = *memmap_switches;
-
- if (power_button_is_pressed())
- *memmap_switches |= EC_SWITCH_POWER_BUTTON_PRESSED;
- else
- *memmap_switches &= ~EC_SWITCH_POWER_BUTTON_PRESSED;
-
- if (!IS_ENABLED(CONFIG_LID_SWITCH) || lid_is_open())
- *memmap_switches |= EC_SWITCH_LID_OPEN;
- else
- *memmap_switches &= ~EC_SWITCH_LID_OPEN;
-
- if ((crec_flash_get_protect() & EC_FLASH_PROTECT_GPIO_ASSERTED) == 0)
- *memmap_switches |= EC_SWITCH_WRITE_PROTECT_DISABLED;
- else
- *memmap_switches &= ~EC_SWITCH_WRITE_PROTECT_DISABLED;
-
-#ifdef CONFIG_SWITCH_DEDICATED_RECOVERY
- if (gpio_get_level(GPIO_RECOVERY_L) == 0)
- *memmap_switches |= EC_SWITCH_DEDICATED_RECOVERY;
- else
- *memmap_switches &= ~EC_SWITCH_DEDICATED_RECOVERY;
-#endif
-
- if (prev != *memmap_switches)
- CPRINTS("SW 0x%02x", *memmap_switches);
-}
-DECLARE_DEFERRED(switch_update);
-DECLARE_HOOK(HOOK_LID_CHANGE, switch_update, HOOK_PRIO_DEFAULT);
-DECLARE_HOOK(HOOK_POWER_BUTTON_CHANGE, switch_update, HOOK_PRIO_DEFAULT);
-
-static void switch_init(void)
-{
- /* Set up memory-mapped switch positions */
- memmap_switches = host_get_memmap(EC_MEMMAP_SWITCHES);
- *memmap_switches = 0;
-
- switch_update();
-
- /* Switch data is now present */
- *host_get_memmap(EC_MEMMAP_SWITCHES_VERSION) = 1;
-
-#ifdef CONFIG_SWITCH_DEDICATED_RECOVERY
- /* Enable interrupts, now that we've initialized */
- gpio_enable_interrupt(GPIO_RECOVERY_L);
-#endif
-
- /*
- * TODO(crosbug.com/p/23793): It's weird that flash_common.c owns
- * reading the write protect signal, but we enable the interrupt for it
- * here. Take ownership of WP back, or refactor it to its own module.
- */
-#ifdef CONFIG_WP_ACTIVE_HIGH
- gpio_enable_interrupt(GPIO_WP);
-#else
- gpio_enable_interrupt(GPIO_WP_L);
-#endif
-}
-DECLARE_HOOK(HOOK_INIT, switch_init, HOOK_PRIO_INIT_SWITCH);
-
-void switch_interrupt(enum gpio_signal signal)
-{
- hook_call_deferred(&switch_update_data, 0);
-}
-
-#ifdef CONFIG_CMD_MMAPINFO
-static int command_mmapinfo(int argc, char **argv)
-{
- uint8_t *memmap_switches = host_get_memmap(EC_MEMMAP_SWITCHES);
- uint8_t val = *memmap_switches;
- int i;
- const char *explanation[] = {
- "lid_open",
- "powerbtn",
- "wp_off",
- "kbd_rec",
- "gpio_rec",
- "fake_dev",
- };
- ccprintf("memmap switches = 0x%x\n", val);
- for (i = 0; i < ARRAY_SIZE(explanation); i++)
- if (val & BIT(i))
- ccprintf(" %s\n", explanation[i]);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(mmapinfo, command_mmapinfo,
- NULL,
- "Print memmap switch state");
-#endif
diff --git a/common/temp_sensor.c b/common/temp_sensor.c
deleted file mode 100644
index 69d440a6d5..0000000000
--- a/common/temp_sensor.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/* Copyright 2012 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.
- */
-
-/* Temperature sensor module for Chrome EC */
-
-#include "common.h"
-#include "console.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "task.h"
-#include "temp_sensor.h"
-#include "thermal.h"
-#include "timer.h"
-#include "util.h"
-
-#ifdef CONFIG_ZEPHYR
-#include "temp_sensor/temp_sensor.h"
-#endif
-
-int temp_sensor_read(enum temp_sensor_id id, int *temp_ptr)
-{
- const struct temp_sensor_t *sensor;
-
- if (id < 0 || id >= TEMP_SENSOR_COUNT)
- return EC_ERROR_INVAL;
- sensor = temp_sensors + id;
-
-#ifdef CONFIG_ZEPHYR
- return sensor->read(sensor, temp_ptr);
-#else
- return sensor->read(sensor->idx, temp_ptr);
-#endif
-}
-
-static void update_mapped_memory(void)
-{
- int i, t;
- uint8_t *mptr = host_get_memmap(EC_MEMMAP_TEMP_SENSOR);
-
- for (i = 0; i < TEMP_SENSOR_COUNT; i++, mptr++) {
- /*
- * Switch to second range if first one is full, or stop if
- * second range is also full.
- */
- if (i == EC_TEMP_SENSOR_ENTRIES)
- mptr = host_get_memmap(EC_MEMMAP_TEMP_SENSOR_B);
- else if (i >= EC_TEMP_SENSOR_ENTRIES +
- EC_TEMP_SENSOR_B_ENTRIES)
- break;
-
- switch (temp_sensor_read(i, &t)) {
- case EC_ERROR_NOT_POWERED:
- *mptr = EC_TEMP_SENSOR_NOT_POWERED;
- break;
- case EC_ERROR_NOT_CALIBRATED:
- *mptr = EC_TEMP_SENSOR_NOT_CALIBRATED;
- break;
- case EC_SUCCESS:
- *mptr = t - EC_TEMP_SENSOR_OFFSET;
- break;
- default:
- *mptr = EC_TEMP_SENSOR_ERROR;
- }
- }
-}
-/* Run after other TEMP tasks, so sensors will have updated first. */
-DECLARE_HOOK(HOOK_SECOND, update_mapped_memory, HOOK_PRIO_TEMP_SENSOR_DONE);
-
-static void temp_sensor_init(void)
-{
- int i;
- uint8_t *base, *base_b;
-
- /*
- * Initialize memory-mapped data so that if a temperature value is read
- * before we actually poll the sensors, we don't return an impossible
- * or out-of-range value.
- */
- base = host_get_memmap(EC_MEMMAP_TEMP_SENSOR);
- base_b = host_get_memmap(EC_MEMMAP_TEMP_SENSOR_B);
- for (i = 0; i < TEMP_SENSOR_COUNT; ++i) {
- if (i < EC_TEMP_SENSOR_ENTRIES)
- base[i] = EC_TEMP_SENSOR_DEFAULT;
- else
- base_b[i - EC_TEMP_SENSOR_ENTRIES] =
- EC_TEMP_SENSOR_DEFAULT;
- }
-
- /* Set the rest of memory region to SENSOR_NOT_PRESENT */
- for (; i < EC_TEMP_SENSOR_ENTRIES + EC_TEMP_SENSOR_B_ENTRIES; ++i) {
- if (i < EC_TEMP_SENSOR_ENTRIES)
- base[i] = EC_TEMP_SENSOR_NOT_PRESENT;
- else
- base_b[i - EC_TEMP_SENSOR_ENTRIES] =
- EC_TEMP_SENSOR_NOT_PRESENT;
- }
-
- /* Temp sensor data is present, with B range supported. */
- *host_get_memmap(EC_MEMMAP_THERMAL_VERSION) = 2;
-}
-DECLARE_HOOK(HOOK_INIT, temp_sensor_init, HOOK_PRIO_DEFAULT);
-
-/*****************************************************************************/
-/* Console commands */
-
-#ifdef CONFIG_CMD_TEMP_SENSOR
-int console_command_temps(int argc, char **argv)
-{
- int t, i;
- int rv, rv1 = EC_SUCCESS;
-
- for (i = 0; i < TEMP_SENSOR_COUNT; ++i) {
- ccprintf(" %-20s: ", temp_sensors[i].name);
- rv = temp_sensor_read(i, &t);
- if (rv)
- rv1 = rv;
-
- switch (rv) {
- case EC_SUCCESS:
- ccprintf("%d K = %d C", t, K_TO_C(t));
-#ifdef CONFIG_THROTTLE_AP
- if (thermal_params[i].temp_fan_off &&
- thermal_params[i].temp_fan_max)
- ccprintf(" %d%%",
- thermal_fan_percent(
- thermal_params[i].temp_fan_off,
- thermal_params[i].temp_fan_max,
- t));
-#endif
- ccprintf("\n");
- break;
- case EC_ERROR_NOT_POWERED:
- ccprintf("Not powered\n");
- break;
- case EC_ERROR_NOT_CALIBRATED:
- ccprintf("Not calibrated\n");
- break;
- default:
- ccprintf("Error %d\n", rv);
- }
- }
-
- return rv1;
-}
-DECLARE_CONSOLE_COMMAND(temps, console_command_temps,
- NULL,
- "Print temp sensors");
-#endif
-
-/*****************************************************************************/
-/* Host commands */
-
-enum ec_status temp_sensor_command_get_info(struct host_cmd_handler_args *args)
-{
- const struct ec_params_temp_sensor_get_info *p = args->params;
- struct ec_response_temp_sensor_get_info *r = args->response;
- int id = p->id;
-
- if (id >= TEMP_SENSOR_COUNT)
- return EC_RES_ERROR;
-
- strzcpy(r->sensor_name, temp_sensors[id].name, sizeof(r->sensor_name));
- r->sensor_type = temp_sensors[id].type;
-
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_TEMP_SENSOR_GET_INFO,
- temp_sensor_command_get_info,
- EC_VER_MASK(0));
diff --git a/common/test_util.c b/common/test_util.c
deleted file mode 100644
index b23f85509b..0000000000
--- a/common/test_util.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/* Copyright 2013 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.
- *
- * Test utilities.
- */
-
-#if defined(TEST_COVERAGE) || defined(TEST_HOSTTEST)
-/* We need signal() and exit() only when building to run on the host. */
-#include <signal.h>
-#include <stdlib.h>
-#endif
-
-#include "console.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "system.h"
-#include "task.h"
-#include "test_util.h"
-#include "util.h"
-
-struct test_util_tag {
- uint8_t error_count;
-};
-
-#define TEST_UTIL_SYSJUMP_TAG 0x5455 /* "TU" */
-#define TEST_UTIL_SYSJUMP_VERSION 1
-
-int __test_error_count;
-
-/* Weak reference function as an entry point for unit test */
-test_mockable void run_test(int argc, char **argv) { }
-
-/* Default mock test init */
-test_mockable void test_init(void) { }
-
-/* Default mock before test */
-test_mockable void before_test(void) { }
-
-/* Default mock after test */
-test_mockable void after_test(void) { }
-
-#ifdef TEST_COVERAGE
-extern void __gcov_flush(void);
-
-void emulator_flush(void)
-{
- __gcov_flush();
-}
-#else
-void emulator_flush(void)
-{
-}
-#endif
-
-#if defined(TEST_HOSTTEST) || defined(TEST_COVERAGE)
-/* Host-based unit tests need to exit(0) when they receive a SIGTERM. */
-void test_end_hook(int sig)
-{
- emulator_flush();
- exit(0);
-}
-
-void register_test_end_hook(void)
-{
- signal(SIGTERM, test_end_hook);
-}
-#else
-void register_test_end_hook(void)
-{
-}
-#endif
-
-void test_reset(void)
-{
- if (!system_jumped_to_this_image())
- __test_error_count = 0;
-}
-
-void test_pass(void)
-{
- ccprintf("Pass!\n");
-}
-
-void test_fail(void)
-{
- ccprintf("Fail!\n");
-}
-
-void test_print_result(void)
-{
- if (__test_error_count)
- ccprintf("Fail! (%d tests)\n", __test_error_count);
- else
- ccprintf("Pass!\n");
-}
-
-int test_get_error_count(void)
-{
- return __test_error_count;
-}
-
-uint32_t test_get_state(void)
-{
- uint32_t state;
-
- system_get_scratchpad(&state);
- return state;
-}
-
-test_mockable void test_clean_up(void)
-{
-}
-
-void test_reboot_to_next_step(enum test_state_t step)
-{
- ccprintf("Rebooting to next test step...\n");
- cflush();
- system_set_scratchpad(TEST_STATE_MASK(step));
- system_reset(SYSTEM_RESET_HARD);
-}
-
-test_mockable void test_run_step(uint32_t state)
-{
-}
-
-void test_run_multistep(void)
-{
- uint32_t state = test_get_state();
-
- if (state & TEST_STATE_MASK(TEST_STATE_PASSED)) {
- test_clean_up();
- system_set_scratchpad(0);
- test_pass();
- } else if (state & TEST_STATE_MASK(TEST_STATE_FAILED)) {
- test_clean_up();
- system_set_scratchpad(0);
- test_fail();
- }
-
- if (state & TEST_STATE_STEP_1 || state == 0) {
- task_wait_event(-1); /* Wait for run_test() */
- test_run_step(TEST_STATE_MASK(TEST_STATE_STEP_1));
- } else {
- test_run_step(state);
- }
-}
-
-#ifdef HAS_TASK_HOSTCMD
-int test_send_host_command(int command, int version, const void *params,
- int params_size, void *resp, int resp_size)
-{
- struct host_cmd_handler_args args;
-
- args.version = version;
- args.command = command;
- args.params = params;
- args.params_size = params_size;
- args.response = resp;
- args.response_max = resp_size;
- args.response_size = 0;
-
- return host_command_process(&args);
-}
-#endif /* TASK_HAS_HOSTCMD */
-
-/* Linear congruential pseudo random number generator */
-uint32_t prng(uint32_t seed)
-{
- return 22695477 * seed + 1;
-}
-
-uint32_t prng_no_seed(void)
-{
- static uint32_t seed = 0x1234abcd;
- return seed = prng(seed);
-}
-
-static void restore_state(void)
-{
- const struct test_util_tag *tag;
- int version, size;
-
- tag = (const struct test_util_tag *)system_get_jump_tag(
- TEST_UTIL_SYSJUMP_TAG, &version, &size);
- if (tag && version == TEST_UTIL_SYSJUMP_VERSION &&
- size == sizeof(*tag))
- __test_error_count = tag->error_count;
- else
- __test_error_count = 0;
-}
-DECLARE_HOOK(HOOK_INIT, restore_state, HOOK_PRIO_DEFAULT);
-
-static void preserve_state(void)
-{
- struct test_util_tag tag;
- tag.error_count = __test_error_count;
- system_add_jump_tag(TEST_UTIL_SYSJUMP_TAG, TEST_UTIL_SYSJUMP_VERSION,
- sizeof(tag), &tag);
-}
-DECLARE_HOOK(HOOK_SYSJUMP, preserve_state, HOOK_PRIO_DEFAULT);
-
-static int command_run_test(int argc, char **argv)
-{
- run_test(argc, argv);
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(runtest, command_run_test,
- NULL, NULL);
-
-#ifndef CONFIG_ZEPHYR
-void z_ztest_run_test_suite(const char *name, struct unit_test *suite)
-{
- test_reset();
-
- while (suite->test) {
- suite->setup();
- RUN_TEST(suite->test);
- suite->teardown();
- suite++;
- }
-
- ccprintf("%s: ", name);
- test_print_result();
-}
-#endif /* CONFIG_ZEPHYR */
diff --git a/common/thermal.c b/common/thermal.c
deleted file mode 100644
index e9750931be..0000000000
--- a/common/thermal.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/* Copyright 2012 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.
- */
-
-/* NEW thermal engine module for Chrome EC. This is a completely different
- * implementation from the original version that shipped on Link.
- */
-
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "fan.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "temp_sensor.h"
-#include "thermal.h"
-#include "throttle_ap.h"
-#include "timer.h"
-#include "util.h"
-
-#ifdef CONFIG_ZEPHYR
-#include "temp_sensor/temp_sensor.h"
-#endif
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_THERMAL, outstr)
-#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ## args)
-
-/*****************************************************************************/
-/* EC-specific thermal controls */
-
-test_mockable_static void smi_sensor_failure_warning(void)
-{
- CPRINTS("can't read any temp sensors!");
- host_set_single_event(EC_HOST_EVENT_THERMAL);
-}
-
-int thermal_fan_percent(int low, int high, int cur)
-{
- if (cur < low)
- return 0;
- if (cur > high)
- return 100;
- return 100 * (cur - low) / (high - low);
-}
-
-/* The logic below is hard-coded for only three thresholds: WARN, HIGH, HALT.
- * This is just a validity check to be sure we catch any changes in thermal.h
- */
-BUILD_ASSERT(EC_TEMP_THRESH_COUNT == 3);
-
-/* Keep track of which thresholds have triggered */
-static cond_t cond_hot[EC_TEMP_THRESH_COUNT];
-
-/* thermal sensor read delay */
-#if defined(CONFIG_TEMP_SENSOR_POWER_GPIO) && \
- defined(CONFIG_TEMP_SENSOR_FIRST_READ_DELAY_MS)
-static int first_read_delay = CONFIG_TEMP_SENSOR_FIRST_READ_DELAY_MS;
-#endif
-
-static void thermal_control(void)
-{
- int i, j, t, rv, f;
- int count_over[EC_TEMP_THRESH_COUNT];
- int count_under[EC_TEMP_THRESH_COUNT];
- int num_valid_limits[EC_TEMP_THRESH_COUNT];
- int num_sensors_read;
- int fmax;
- int temp_fan_configured;
-
-#ifdef CONFIG_CUSTOM_FAN_CONTROL
- int temp[TEMP_SENSOR_COUNT];
-#endif
-
- /* add delay to ensure thermal sensor is ready when EC boot */
-#if defined(CONFIG_TEMP_SENSOR_POWER_GPIO) && \
- defined(CONFIG_TEMP_SENSOR_FIRST_READ_DELAY_MS)
- if (first_read_delay != 0) {
- msleep(first_read_delay);
- first_read_delay = 0;
- }
-#endif
-
- /* Get ready to count things */
- memset(count_over, 0, sizeof(count_over));
- memset(count_under, 0, sizeof(count_under));
- memset(num_valid_limits, 0, sizeof(num_valid_limits));
- num_sensors_read = 0;
- fmax = 0;
- temp_fan_configured = 0;
-
- /* go through all the sensors */
- for (i = 0; i < TEMP_SENSOR_COUNT; ++i) {
-
- /* read one */
- rv = temp_sensor_read(i, &t);
-
-#ifdef CONFIG_CUSTOM_FAN_CONTROL
- /* Store all sensors value */
- temp[i] = K_TO_C(t);
-#endif
-
- if (rv != EC_SUCCESS)
- continue;
- else
- num_sensors_read++;
-
- /* check all the limits */
- for (j = 0; j < EC_TEMP_THRESH_COUNT; j++) {
- int limit = thermal_params[i].temp_host[j];
- int release = thermal_params[i].temp_host_release[j];
- if (limit) {
- num_valid_limits[j]++;
- if (t > limit) {
- count_over[j]++;
- } else if (release) {
- if (t < release)
- count_under[j]++;
- } else if (t < limit) {
- count_under[j]++;
- }
- }
- }
-
- /* figure out the max fan needed, too */
- if (thermal_params[i].temp_fan_off &&
- thermal_params[i].temp_fan_max) {
- f = thermal_fan_percent(thermal_params[i].temp_fan_off,
- thermal_params[i].temp_fan_max,
- t);
- if (f > fmax)
- fmax = f;
-
- temp_fan_configured = 1;
- }
- }
-
- if (!num_sensors_read) {
- /*
- * Trigger a SMI event if we can't read any sensors.
- *
- * In theory we could do something more elaborate like forcing
- * the system to shut down if no sensors are available after
- * several retries. This is a very unlikely scenario -
- * particularly on LM4-based boards, since the LM4 has its own
- * internal temp sensor. It's most likely to occur during
- * bringup of a new board, where we haven't debugged the I2C
- * bus to the sensors; forcing a shutdown in that case would
- * merely hamper board bringup.
- *
- * If in G3, then there is no need trigger an SMI event since
- * the AP is off and this can be an expected state if
- * temperature sensors are powered by a power rail that's only
- * on if the AP is out of G3. Note this could be 'ANY_OFF' as
- * well, but that causes the thermal unit test to fail.
- */
- if (!chipset_in_state(CHIPSET_STATE_HARD_OFF))
- smi_sensor_failure_warning();
- return;
- }
-
- /* See what the aggregated limits are. Any temp over the limit
- * means it's hot, but all temps have to be under the limit to
- * be cool again.
- */
- for (j = 0; j < EC_TEMP_THRESH_COUNT; j++) {
- if (count_over[j])
- cond_set_true(&cond_hot[j]);
- else if (count_under[j] == num_valid_limits[j])
- cond_set_false(&cond_hot[j]);
- }
-
- /* What do we do about it? (note hard-coded logic). */
-
- if (cond_went_true(&cond_hot[EC_TEMP_THRESH_HALT])) {
- CPRINTS("thermal SHUTDOWN");
-
- /* Print temperature sensor values before shutting down AP */
- if (IS_ENABLED(CONFIG_CMD_TEMP_SENSOR)) {
- console_command_temps(1, NULL);
- cflush();
- }
-
- chipset_force_shutdown(CHIPSET_SHUTDOWN_THERMAL);
- } else if (cond_went_false(&cond_hot[EC_TEMP_THRESH_HALT])) {
- /* We don't reboot automatically - the user has to push
- * the power button. It's likely that we can't even
- * detect this sensor transition until then, but we
- * do have to check in order to clear the cond_t.
- */
- CPRINTS("thermal no longer shutdown");
- }
-
- if (cond_went_true(&cond_hot[EC_TEMP_THRESH_HIGH])) {
- CPRINTS("thermal HIGH");
- throttle_ap(THROTTLE_ON, THROTTLE_HARD, THROTTLE_SRC_THERMAL);
- } else if (cond_went_false(&cond_hot[EC_TEMP_THRESH_HIGH])) {
- CPRINTS("thermal no longer high");
- throttle_ap(THROTTLE_OFF, THROTTLE_HARD, THROTTLE_SRC_THERMAL);
- }
-
- if (cond_went_true(&cond_hot[EC_TEMP_THRESH_WARN])) {
- CPRINTS("thermal WARN");
- throttle_ap(THROTTLE_ON, THROTTLE_SOFT, THROTTLE_SRC_THERMAL);
- } else if (cond_went_false(&cond_hot[EC_TEMP_THRESH_WARN])) {
- CPRINTS("thermal no longer warn");
- throttle_ap(THROTTLE_OFF, THROTTLE_SOFT, THROTTLE_SRC_THERMAL);
- }
-
- if (temp_fan_configured) {
-#ifdef CONFIG_FANS
-#ifdef CONFIG_CUSTOM_FAN_CONTROL
- for (i = 0; i < fan_get_count(); i++) {
- if (!is_thermal_control_enabled(i))
- continue;
-
- board_override_fan_control(i, temp);
- }
-#else
- /* TODO(crosbug.com/p/23797): For now, we just treat all
- * fans the same. It would be better if we could assign
- * different thermal profiles to each fan - in case one
- * fan cools the CPU while another cools the radios or
- * battery.
- */
- for (i = 0; i < fan_get_count(); i++)
- fan_set_percent_needed(i, fmax);
-#endif
-#endif
- }
-}
-
-/* Wait until after the sensors have been read */
-DECLARE_HOOK(HOOK_SECOND, thermal_control, HOOK_PRIO_TEMP_SENSOR_DONE);
-
-/*****************************************************************************/
-/* Console commands */
-
-static int command_thermalget(int argc, char **argv)
-{
- int i;
-
- ccprintf("sensor warn high halt fan_off fan_max name\n");
- for (i = 0; i < TEMP_SENSOR_COUNT; i++) {
- ccprintf(" %2d %3d %3d %3d %3d %3d %s\n",
- i,
- thermal_params[i].temp_host[EC_TEMP_THRESH_WARN],
- thermal_params[i].temp_host[EC_TEMP_THRESH_HIGH],
- thermal_params[i].temp_host[EC_TEMP_THRESH_HALT],
- thermal_params[i].temp_fan_off,
- thermal_params[i].temp_fan_max,
- temp_sensors[i].name);
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(thermalget, command_thermalget,
- NULL,
- "Print thermal parameters (degrees Kelvin)");
-
-
-static int command_thermalset(int argc, char **argv)
-{
- unsigned int n;
- int i, val;
- char *e;
-
- if (argc < 3 || argc > 7)
- return EC_ERROR_PARAM_COUNT;
-
- n = (unsigned int)strtoi(argv[1], &e, 0);
- if (*e)
- return EC_ERROR_PARAM1;
-
- for (i = 2; i < argc; i++) {
- val = strtoi(argv[i], &e, 0);
- if (*e)
- return EC_ERROR_PARAM1 + i - 1;
- if (val < 0)
- continue;
- switch (i) {
- case 2:
- thermal_params[n].temp_host[EC_TEMP_THRESH_WARN] = val;
- break;
- case 3:
- thermal_params[n].temp_host[EC_TEMP_THRESH_HIGH] = val;
- break;
- case 4:
- thermal_params[n].temp_host[EC_TEMP_THRESH_HALT] = val;
- break;
- case 5:
- thermal_params[n].temp_fan_off = val;
- break;
- case 6:
- thermal_params[n].temp_fan_max = val;
- break;
- }
- }
-
- command_thermalget(0, 0);
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(thermalset, command_thermalset,
- "sensor warn [high [shutdown [fan_off [fan_max]]]]",
- "Set thermal parameters (degrees Kelvin)."
- " Use -1 to skip.");
-
-/*****************************************************************************/
-/* Host commands. We'll reuse the host command number, but this is version 1,
- * not version 0. Different structs, different meanings.
- */
-
-static enum ec_status
-thermal_command_set_threshold(struct host_cmd_handler_args *args)
-{
- const struct ec_params_thermal_set_threshold_v1 *p = args->params;
-
- if (p->sensor_num >= TEMP_SENSOR_COUNT)
- return EC_RES_INVALID_PARAM;
-
- thermal_params[p->sensor_num] = p->cfg;
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_THERMAL_SET_THRESHOLD,
- thermal_command_set_threshold,
- EC_VER_MASK(1));
-
-static enum ec_status
-thermal_command_get_threshold(struct host_cmd_handler_args *args)
-{
- const struct ec_params_thermal_get_threshold_v1 *p = args->params;
- struct ec_thermal_config *r = args->response;
-
- if (p->sensor_num >= TEMP_SENSOR_COUNT)
- return EC_RES_INVALID_PARAM;
-
- *r = thermal_params[p->sensor_num];
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_THERMAL_GET_THRESHOLD,
- thermal_command_get_threshold,
- EC_VER_MASK(1));
diff --git a/common/throttle_ap.c b/common/throttle_ap.c
deleted file mode 100644
index cfa97d93a5..0000000000
--- a/common/throttle_ap.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/* Copyright 2013 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.
- */
-
-/* Common chipset throttling code for Chrome EC */
-
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "dptf.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "task.h"
-#include "throttle_ap.h"
-#include "timer.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_THERMAL, outstr)
-#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ## args)
-
-#define PROCHOT_IN_DEBOUNCE_US (100 * 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;
-
-void throttle_ap(enum throttle_level level,
- enum throttle_type type,
- enum throttle_sources source)
-{
- uint32_t tmpval, bitmask;
-
- mutex_lock(&throttle_mutex);
-
- bitmask = BIT(source);
-
- switch (level) {
- case THROTTLE_ON:
- throttle_request[type] |= bitmask;
- break;
- case THROTTLE_OFF:
- throttle_request[type] &= ~bitmask;
- break;
- }
-
- tmpval = throttle_request[type]; /* save for printing */
-
- switch (type) {
- case THROTTLE_SOFT:
-#ifdef HAS_TASK_HOSTCMD
- host_throttle_cpu(tmpval);
-#endif
- break;
- case THROTTLE_HARD:
-#ifdef CONFIG_CHIPSET_CAN_THROTTLE
- chipset_throttle_cpu(tmpval);
-#endif
- break;
-
- case NUM_THROTTLE_TYPES:
- /* Make the compiler shut up. Don't use 'default', because
- * we still want to catch any new types.
- */
- break;
- }
-
- mutex_unlock(&throttle_mutex);
-
- /* print outside the mutex */
- CPRINTS("set AP throttling type %d to %s (0x%08x)",
- type, tmpval ? "on" : "off", tmpval);
-
-}
-
-static void prochot_input_deferred(void)
-{
- int prochot_in;
-
- /*
- * Shouldn't be possible, but better to protect against buffer
- * overflow
- */
- ASSERT(signal_is_gpio(gpio_prochot_in));
-
- prochot_in = gpio_get_level(gpio_prochot_in);
-
- if (IS_ENABLED(CONFIG_CPU_PROCHOT_ACTIVE_LOW))
- prochot_in = !prochot_in;
-
- if (prochot_in == debounced_prochot_in)
- return;
-
- /*
- * b/173180788 Confirmed from Intel internal that SLP_S3# asserts low
- * about 10us before PROCHOT# asserts low, which means that
- * the CPU is already in reset and therefore the PROCHOT#
- * asserting low is normal behavior and not a concern
- * for PROCHOT# event. Ignore all PROCHOT changes while the AP is off
- */
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
- return;
-
- debounced_prochot_in = prochot_in;
-
- if (debounced_prochot_in) {
- CPRINTS("External PROCHOT assertion detected");
-#ifdef CONFIG_FANS
- dptf_set_fan_duty_target(100);
-#endif
- } else {
- CPRINTS("External PROCHOT condition cleared");
-#ifdef CONFIG_FANS
- /* Revert to automatic control of the fan */
- dptf_set_fan_duty_target(-1);
-#endif
- }
-}
-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.
- */
- hook_call_deferred(&prochot_input_deferred_data,
- PROCHOT_IN_DEBOUNCE_US);
-}
-
-/*****************************************************************************/
-/* Console commands */
-#ifdef CONFIG_CMD_APTHROTTLE
-static int command_apthrottle(int argc, char **argv)
-{
- int i;
- uint32_t tmpval;
-
- for (i = 0; i < NUM_THROTTLE_TYPES; i++) {
- mutex_lock(&throttle_mutex);
- tmpval = throttle_request[i];
- mutex_unlock(&throttle_mutex);
-
- ccprintf("AP throttling type %d is %s (0x%08x)\n", i,
- tmpval ? "on" : "off", tmpval);
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(apthrottle, command_apthrottle,
- NULL,
- "Display the AP throttling state");
-#endif
diff --git a/common/update_fw.c b/common/update_fw.c
deleted file mode 100644
index 068758e7b0..0000000000
--- a/common/update_fw.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/* Copyright 2016 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.
- */
-
-#include "byteorder.h"
-#include "console.h"
-#include "flash.h"
-#include "hooks.h"
-#include "include/compile_time_macros.h"
-#include "rollback.h"
-#include "rwsig.h"
-#include "sha256.h"
-#include "system.h"
-#include "uart.h"
-#include "update_fw.h"
-#include "util.h"
-#include "vb21_struct.h"
-#include "vboot.h"
-
-#if defined(CONFIG_TOUCHPAD_VIRTUAL_OFF) && defined(CONFIG_TOUCHPAD_HASH_FW)
-#define CONFIG_TOUCHPAD_FW_CHUNKS \
- (CONFIG_TOUCHPAD_VIRTUAL_SIZE / CONFIG_UPDATE_PDU_SIZE)
-
-#include "touchpad_fw_hash.h"
-
-BUILD_ASSERT(sizeof(touchpad_fw_hashes) ==
- (CONFIG_TOUCHPAD_FW_CHUNKS * SHA256_DIGEST_SIZE));
-BUILD_ASSERT(sizeof(touchpad_fw_hashes[0]) == SHA256_DIGEST_SIZE);
-
-BUILD_ASSERT(sizeof(touchpad_fw_full_hash) == SHA256_DIGEST_SIZE);
-#endif
-
-#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args)
-
-/* Section to be updated (i.e. not the current section). */
-struct {
- uint32_t base_offset;
- uint32_t top_offset;
-} update_section;
-
-#ifdef CONFIG_TOUCHPAD_VIRTUAL_OFF
-/*
- * Check if a block is within touchpad FW virtual address region, and
- * is therefore meant to be flashed to the touchpad.
- */
-static int is_touchpad_block(uint32_t block_offset, size_t body_size)
-{
- return (block_offset >= CONFIG_TOUCHPAD_VIRTUAL_OFF) &&
- (block_offset + body_size) <=
- (CONFIG_TOUCHPAD_VIRTUAL_OFF +
- CONFIG_TOUCHPAD_VIRTUAL_SIZE);
-}
-#endif
-
-/*
- * Verify that the passed in block fits into the valid area. If it does, and
- * is destined to the base address of the area - erase the area contents.
- *
- * Return success, or indication of an erase failure or chunk not fitting into
- * valid area.
- *
- * TODO(b/36375666): Each board/chip should be able to re-define this.
- */
-static uint8_t check_update_chunk(uint32_t block_offset, size_t body_size)
-{
- uint32_t base;
- uint32_t size;
-
- /* Is this an RW chunk? */
- if (update_section.base_offset != update_section.top_offset &&
- (block_offset >= update_section.base_offset) &&
- ((block_offset + body_size) <= update_section.top_offset)) {
-
- base = update_section.base_offset;
- size = update_section.top_offset -
- update_section.base_offset;
- /*
- * If this is the first chunk for this section, it needs to
- * be erased.
- */
- if (block_offset == base) {
- if (crec_flash_physical_erase(base, size) !=
- EC_SUCCESS) {
- CPRINTF("%s:%d erase failure of 0x%x..+0x%x\n",
- __func__, __LINE__, base, size);
- return UPDATE_ERASE_FAILURE;
- }
- }
-
- return UPDATE_SUCCESS;
- }
-
-#ifdef CONFIG_TOUCHPAD_VIRTUAL_OFF
- if (is_touchpad_block(block_offset, body_size))
- return UPDATE_SUCCESS;
-#endif
-
- CPRINTF("%s:%d %x, %d section base %x top %x\n",
- __func__, __LINE__,
- block_offset, body_size,
- update_section.base_offset,
- update_section.top_offset);
-
- return UPDATE_BAD_ADDR;
-
-}
-
-int update_pdu_valid(struct update_command *cmd_body, size_t cmd_size)
-{
- return 1;
-}
-
-static int chunk_came_too_soon(uint32_t block_offset)
-{
- return 0;
-}
-
-static void new_chunk_written(uint32_t block_offset)
-{
-}
-
-static int contents_allowed(uint32_t block_offset,
- size_t body_size, void *update_data)
-{
-#if defined(CONFIG_TOUCHPAD_VIRTUAL_OFF) && defined(CONFIG_TOUCHPAD_HASH_FW)
- if (is_touchpad_block(block_offset, body_size)) {
- struct sha256_ctx ctx;
- uint8_t *tmp;
- uint32_t fw_offset = block_offset - CONFIG_TOUCHPAD_VIRTUAL_OFF;
- unsigned int chunk = fw_offset / CONFIG_UPDATE_PDU_SIZE;
- int good = 0;
-
- if (chunk >= CONFIG_TOUCHPAD_FW_CHUNKS ||
- (fw_offset % CONFIG_UPDATE_PDU_SIZE) != 0) {
- CPRINTF("%s: TP invalid offset %08x\n",
- __func__, fw_offset);
- return 0;
- }
-
- SHA256_init(&ctx);
- SHA256_update(&ctx, update_data, body_size);
- tmp = SHA256_final(&ctx);
-
- good = !memcmp(tmp, touchpad_fw_hashes[chunk],
- SHA256_DIGEST_SIZE);
-
- CPRINTF("%s: TP %08x %02x..%02x (%s)\n", __func__,
- fw_offset, tmp[0], tmp[31], good ? "GOOD" : "BAD");
-
- return good;
- }
-#endif
- return 1;
-}
-
-/*
- * Setup internal state (e.g. valid sections, and fill first response).
- *
- * Assumes rpdu is already prefilled with 0, and that version has already
- * been set. May set a return_value != 0 on error.
- */
-void fw_update_start(struct first_response_pdu *rpdu)
-{
- const char *version;
-#ifdef CONFIG_RWSIG_TYPE_RWSIG
- const struct vb21_packed_key *vb21_key;
-#endif
-
- rpdu->header_type = htobe16(UPDATE_HEADER_TYPE_COMMON);
-
- /* Determine the valid update section. */
- switch (system_get_image_copy()) {
- case EC_IMAGE_RO:
- /* RO running, so update RW */
- update_section.base_offset = CONFIG_RW_MEM_OFF;
- update_section.top_offset = CONFIG_RW_MEM_OFF + CONFIG_RW_SIZE;
- version = system_get_version(EC_IMAGE_RW);
- break;
- case EC_IMAGE_RW:
- /* RW running, so update RO */
- update_section.base_offset = CONFIG_RO_MEM_OFF;
- update_section.top_offset = CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE;
- version = system_get_version(EC_IMAGE_RO);
- break;
- default:
- CPRINTF("%s:%d\n", __func__, __LINE__);
- rpdu->return_value = htobe32(UPDATE_GEN_ERROR);
- return;
- }
-
- rpdu->common.maximum_pdu_size = htobe32(CONFIG_UPDATE_PDU_SIZE);
- rpdu->common.flash_protection = htobe32(crec_flash_get_protect());
- rpdu->common.offset = htobe32(update_section.base_offset);
- if (version)
- memcpy(rpdu->common.version, version,
- sizeof(rpdu->common.version));
-
-#ifdef CONFIG_ROLLBACK
- rpdu->common.min_rollback = htobe32(rollback_get_minimum_version());
-#else
- rpdu->common.min_rollback = htobe32(-1);
-#endif
-
-#ifdef CONFIG_RWSIG_TYPE_RWSIG
- vb21_key = vb21_get_packed_key();
- rpdu->common.key_version = htobe32(vb21_key->key_version);
-#endif
-
-#ifdef HAS_TASK_RWSIG
- /* Do not allow the update to start if RWSIG is still running. */
- if (rwsig_get_status() == RWSIG_IN_PROGRESS) {
- CPRINTF("RWSIG in progress\n");
- rpdu->return_value = htobe32(UPDATE_RWSIG_BUSY);
- }
-#endif
-}
-
-void fw_update_command_handler(void *body,
- size_t cmd_size,
- size_t *response_size)
-{
- struct update_command *cmd_body = body;
- void *update_data;
- uint8_t *error_code = body; /* Cache the address for code clarity. */
- size_t body_size;
- uint32_t block_offset;
-
- *response_size = 1; /* One byte response unless this is a start PDU. */
-
- if (cmd_size < sizeof(struct update_command)) {
- CPRINTF("%s:%d\n", __func__, __LINE__);
- *error_code = UPDATE_GEN_ERROR;
- return;
- }
- body_size = cmd_size - sizeof(struct update_command);
-
- if (!cmd_body->block_base && !body_size) {
- struct first_response_pdu *rpdu = body;
-
- /*
- * This is the connection establishment request, the response
- * allows the server to decide what sections of the image to
- * send to program into the flash.
- */
-
- /* First, prepare the response structure. */
- memset(rpdu, 0, sizeof(*rpdu));
- /*
- * TODO(b/36375666): The response size can be shorter depending
- * on which board-specific type of response we provide. This
- * may send trailing 0 bytes, which should be harmless.
- */
- *response_size = sizeof(*rpdu);
- rpdu->protocol_version = htobe16(UPDATE_PROTOCOL_VERSION);
-
- /* Setup internal state (e.g. valid sections, and fill rpdu) */
- fw_update_start(rpdu);
- return;
- }
-
- block_offset = be32toh(cmd_body->block_base);
-
- if (!update_pdu_valid(cmd_body, cmd_size)) {
- *error_code = UPDATE_DATA_ERROR;
- return;
- }
-
- update_data = cmd_body + 1;
- if (!contents_allowed(block_offset, body_size, update_data)) {
- *error_code = UPDATE_ROLLBACK_ERROR;
- return;
- }
-
- /* Check if the block will fit into the valid area. */
- *error_code = check_update_chunk(block_offset, body_size);
- if (*error_code)
- return;
-
- if (chunk_came_too_soon(block_offset)) {
- *error_code = UPDATE_RATE_LIMIT_ERROR;
- return;
- }
-
-#ifdef CONFIG_TOUCHPAD_VIRTUAL_OFF
- if (is_touchpad_block(block_offset, body_size)) {
- if (touchpad_update_write(
- block_offset - CONFIG_TOUCHPAD_VIRTUAL_OFF,
- body_size, update_data) != EC_SUCCESS) {
- *error_code = UPDATE_WRITE_FAILURE;
- CPRINTF("%s:%d update write error\n",
- __func__, __LINE__);
- return;
- }
-
- new_chunk_written(block_offset);
-
- *error_code = UPDATE_SUCCESS;
- return;
- }
-#endif
-
- CPRINTF("update: 0x%x\n", block_offset + CONFIG_PROGRAM_MEMORY_BASE);
- if (crec_flash_physical_write(block_offset, body_size, update_data)
- != EC_SUCCESS) {
- *error_code = UPDATE_WRITE_FAILURE;
- CPRINTF("%s:%d update write error\n", __func__, __LINE__);
- return;
- }
-
- new_chunk_written(block_offset);
-
- /* Verify that data was written properly. */
- if (memcmp(update_data, (void *)
- (block_offset + CONFIG_PROGRAM_MEMORY_BASE),
- body_size)) {
- *error_code = UPDATE_VERIFY_ERROR;
- CPRINTF("%s:%d update verification error\n",
- __func__, __LINE__);
- return;
- }
-
- *error_code = UPDATE_SUCCESS;
-}
-
-void fw_update_complete(void)
-{
-}
diff --git a/common/usb_charger.c b/common/usb_charger.c
deleted file mode 100644
index b8e8038811..0000000000
--- a/common/usb_charger.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Copyright 2015 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.
- */
-
-/*
- * USB charger interface routines. This code assumes that CONFIG_CHARGE_MANAGER
- * is defined and implemented.
- * usb_charger_set_switches() must be implemented by a companion
- * usb_switch driver.
- * In addition, USB switch-specific usb_charger task or interrupt routine
- * is necessary to update charge_manager with detected charger attributes.
- */
-
-#include "charge_manager.h"
-#include "charger.h"
-#include "common.h"
-#include "console.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "stddef.h"
-#include "task.h"
-#include "usb_charge.h"
-#include "usb_pd.h"
-#include "usb_pd_flags.h"
-#include "usbc_ppc.h"
-#include "util.h"
-
-static void update_vbus_supplier(int port, int vbus_level)
-{
- struct charge_port_info charge = {0};
-
- if (vbus_level && !usb_charger_port_is_sourcing_vbus(port)) {
- charge.voltage = USB_CHARGER_VOLTAGE_MV;
- charge.current = USB_CHARGER_MIN_CURR_MA;
- }
-
- charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, port, &charge);
-}
-
-#ifdef CONFIG_USB_PD_5V_EN_CUSTOM
-#define USB_5V_EN(port) board_is_sourcing_vbus(port)
-#elif defined(CONFIG_USBC_PPC)
-#define USB_5V_EN(port) ppc_is_sourcing_vbus(port)
-#elif defined(CONFIG_USB_PD_PPC)
-#define USB_5V_EN(port) tcpci_tcpm_get_src_ctrl(port)
-#elif defined(CONFIG_USB_PD_5V_CHARGER_CTRL)
-#define USB_5V_EN(port) charger_is_sourcing_otg_power(port)
-#elif defined(CONFIG_USB_PD_5V_EN_ACTIVE_LOW)
-#define USB_5V_EN(port) !gpio_get_level(GPIO_USB_C##port##_5V_EN_L)
-#else
-#define USB_5V_EN(port) gpio_get_level(GPIO_USB_C##port##_5V_EN)
-#endif
-
-int usb_charger_port_is_sourcing_vbus(int port)
-{
- if (port == 0)
- return USB_5V_EN(0);
-#if CONFIG_USB_PD_PORT_MAX_COUNT >= 2
- else if (port == 1)
- return USB_5V_EN(1);
-#endif
- /* Not a valid port */
- return 0;
-}
-
-void usb_charger_vbus_change(int port, int vbus_level)
-{
- /* If VBUS has transitioned low, notify PD module directly */
- if (!vbus_level)
- pd_vbus_low(port);
-
- /* Update VBUS supplier and signal VBUS change to USB_CHG task */
- update_vbus_supplier(port, vbus_level);
-
-#ifdef HAS_TASK_USB_CHG_P0
- /* USB Charger task(s) */
- task_set_event(USB_CHG_PORT_TO_TASK_ID(port), USB_CHG_EVENT_VBUS);
-
- /* If we swapped to sourcing, drop any related charge suppliers */
- if (usb_charger_port_is_sourcing_vbus(port))
- usb_charger_reset_charge(port);
-#endif
-
- if ((get_usb_pd_vbus_detect() == USB_PD_VBUS_DETECT_CHARGER) ||
- (get_usb_pd_vbus_detect() == USB_PD_VBUS_DETECT_PPC)) {
- /* USB PD task */
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-void usb_charger_reset_charge(int port)
-{
- charge_manager_update_charge(CHARGE_SUPPLIER_PROPRIETARY,
- port, NULL);
- charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP,
- port, NULL);
- charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP,
- port, NULL);
- charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP,
- port, NULL);
- charge_manager_update_charge(CHARGE_SUPPLIER_OTHER,
- port, NULL);
-#if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0
- charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED,
- port, NULL);
-#endif
-#ifdef CONFIG_WIRELESS_CHARGER_P9221_R7
- charge_manager_update_charge(CHARGE_SUPPLIER_WPC_BPP,
- port, NULL);
- charge_manager_update_charge(CHARGE_SUPPLIER_WPC_EPP,
- port, NULL);
- charge_manager_update_charge(CHARGE_SUPPLIER_WPC_GPP,
- port, NULL);
-#endif
-
-}
-
-static void usb_charger_init(void)
-{
- int i;
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- usb_charger_reset_charge(i);
- /* Initialize VBUS supplier based on whether VBUS is present. */
- update_vbus_supplier(i, pd_is_vbus_present(i));
- }
-}
-DECLARE_HOOK(HOOK_INIT, usb_charger_init, HOOK_PRIO_CHARGE_MANAGER_INIT + 1);
-
-void usb_charger_task(void *u)
-{
- int port = TASK_ID_TO_USB_CHG_PORT(task_get_current());
-
- ASSERT(bc12_ports[port].drv->usb_charger_task);
- bc12_ports[port].drv->usb_charger_task(port);
-}
diff --git a/common/usb_common.c b/common/usb_common.c
deleted file mode 100644
index 786bd118cf..0000000000
--- a/common/usb_common.c
+++ /dev/null
@@ -1,1027 +0,0 @@
-/* Copyright 2019 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.
- */
-
-/*
- * Contains common USB functions shared between the old (i.e. usb_pd_protocol)
- * and the new (i.e. usb_sm_*) USB-C PD stacks.
- */
-
-#include "atomic.h"
-#include "charge_manager.h"
-#include "charge_state.h"
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "ec_commands.h"
-#include "hooks.h"
-#include "stdbool.h"
-#include "host_command.h"
-#include "system.h"
-#include "task.h"
-#include "usb_api.h"
-#include "usb_common.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "usb_pd_dpm.h"
-#include "usb_pd_flags.h"
-#include "usb_pd_tcpm.h"
-#include "usbc_ocp.h"
-#include "usbc_ppc.h"
-#include "util.h"
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#else
-#define CPRINTS(format, args...)
-#define CPRINTF(format, args...)
-#endif
-
-/*
- * If we are trying to upgrade PD firmwares (TCPC chips, retimer, etc), we
- * need to ensure the battery has enough charge for this process. 100mAh
- * is about 5% of most batteries, and it should be enough charge to get us
- * through the EC jump to RW and PD upgrade.
- */
-#define MIN_BATTERY_FOR_PD_UPGRADE_MAH 100 /* mAH */
-
-#if defined(CONFIG_CMD_PD) && defined(CONFIG_CMD_PD_FLASH)
-int hex8tou32(char *str, uint32_t *val)
-{
- char *ptr = str;
- uint32_t tmp = 0;
-
- while (*ptr) {
- char c = *ptr++;
-
- if (c >= '0' && c <= '9')
- tmp = (tmp << 4) + (c - '0');
- else if (c >= 'A' && c <= 'F')
- tmp = (tmp << 4) + (c - 'A' + 10);
- else if (c >= 'a' && c <= 'f')
- tmp = (tmp << 4) + (c - 'a' + 10);
- else
- return EC_ERROR_INVAL;
- }
- if (ptr != str + 8)
- return EC_ERROR_INVAL;
- *val = tmp;
- return EC_SUCCESS;
-}
-
-int remote_flashing(int argc, char **argv)
-{
- int port, cnt, cmd;
- uint32_t data[VDO_MAX_SIZE-1];
- char *e;
- static int flash_offset[CONFIG_USB_PD_PORT_MAX_COUNT];
-
- if (argc < 4 || argc > (VDO_MAX_SIZE + 4 - 1))
- return EC_ERROR_PARAM_COUNT;
-
- port = strtoi(argv[1], &e, 10);
- if (*e || port >= board_get_usb_pd_port_count())
- return EC_ERROR_PARAM2;
-
- cnt = 0;
- if (!strcasecmp(argv[3], "erase")) {
- cmd = VDO_CMD_FLASH_ERASE;
- flash_offset[port] = 0;
- ccprintf("ERASE ...");
- } else if (!strcasecmp(argv[3], "reboot")) {
- cmd = VDO_CMD_REBOOT;
- ccprintf("REBOOT ...");
- } else if (!strcasecmp(argv[3], "signature")) {
- cmd = VDO_CMD_ERASE_SIG;
- ccprintf("ERASE SIG ...");
- } else if (!strcasecmp(argv[3], "info")) {
- cmd = VDO_CMD_READ_INFO;
- ccprintf("INFO...");
- } else if (!strcasecmp(argv[3], "version")) {
- cmd = VDO_CMD_VERSION;
- ccprintf("VERSION...");
- } else {
- int i;
-
- argc -= 3;
- for (i = 0; i < argc; i++)
- if (hex8tou32(argv[i+3], data + i))
- return EC_ERROR_INVAL;
- cmd = VDO_CMD_FLASH_WRITE;
- cnt = argc;
- ccprintf("WRITE %d @%04x ...", argc * 4,
- flash_offset[port]);
- flash_offset[port] += argc * 4;
- }
-
- pd_send_vdm(port, USB_VID_GOOGLE, cmd, data, cnt);
-
- /* Wait until VDM is done */
- while (pd[port].vdm_state > 0)
- task_wait_event(100*MSEC);
-
- ccprintf("DONE %d\n", pd[port].vdm_state);
- return EC_SUCCESS;
-}
-#endif /* defined(CONFIG_CMD_PD) && defined(CONFIG_CMD_PD_FLASH) */
-
-bool pd_firmware_upgrade_check_power_readiness(int port)
-{
- if (IS_ENABLED(HAS_TASK_CHARGER)) {
- struct batt_params batt = { 0 };
- /*
- * Cannot rely on the EC's active charger data as the
- * EC may just rebooted into RW and has not necessarily
- * picked the active charger yet. Charger task may not
- * initialized, so check battery directly.
- * Prevent the upgrade if the battery doesn't have enough
- * charge to finish the upgrade.
- */
- battery_get_params(&batt);
- if (batt.flags & BATT_FLAG_BAD_REMAINING_CAPACITY ||
- batt.remaining_capacity <
- MIN_BATTERY_FOR_PD_UPGRADE_MAH) {
- CPRINTS("C%d: Cannot suspend for upgrade, not "
- "enough battery (%dmAh)!",
- port, batt.remaining_capacity);
- return false;
- }
- } else {
- /* VBUS is present on the port (it is either a
- * source or sink) to provide power, so don't allow
- * PD firmware upgrade on the port.
- */
- if (pd_is_vbus_present(port))
- return false;
- }
-
- return true;
-}
-
-int usb_get_battery_soc(void)
-{
-#if defined(CONFIG_CHARGER)
- return charge_get_percent();
-#elif defined(CONFIG_BATTERY)
- return board_get_battery_soc();
-#else
- return 0;
-#endif
-}
-
-#if defined(CONFIG_USB_PD_PREFER_MV) && defined(PD_PREFER_LOW_VOLTAGE) + \
- defined(PD_PREFER_HIGH_VOLTAGE) > 1
-#error "PD preferred voltage strategy should be mutually exclusive."
-#endif
-
-/*
- * CC values for regular sources and Debug sources (aka DTS)
- *
- * Source type Mode of Operation CC1 CC2
- * ---------------------------------------------
- * Regular Default USB Power RpUSB Open
- * Regular USB-C @ 1.5 A Rp1A5 Open
- * Regular USB-C @ 3 A Rp3A0 Open
- * DTS Default USB Power Rp3A0 Rp1A5
- * DTS USB-C @ 1.5 A Rp1A5 RpUSB
- * DTS USB-C @ 3 A Rp3A0 RpUSB
- */
-
-typec_current_t usb_get_typec_current_limit(enum tcpc_cc_polarity polarity,
- enum tcpc_cc_voltage_status cc1, enum tcpc_cc_voltage_status cc2)
-{
- typec_current_t charge = 0;
- enum tcpc_cc_voltage_status cc;
- enum tcpc_cc_voltage_status cc_alt;
-
- cc = polarity_rm_dts(polarity) ? cc2 : cc1;
- cc_alt = polarity_rm_dts(polarity) ? cc1 : cc2;
-
- switch (cc) {
- case TYPEC_CC_VOLT_RP_3_0:
- if (!cc_is_rp(cc_alt) || cc_alt == TYPEC_CC_VOLT_RP_DEF)
- charge = 3000;
- else if (cc_alt == TYPEC_CC_VOLT_RP_1_5)
- charge = 500;
- break;
- case TYPEC_CC_VOLT_RP_1_5:
- charge = 1500;
- break;
- case TYPEC_CC_VOLT_RP_DEF:
- charge = 500;
- break;
- default:
- break;
- }
-
- if (IS_ENABLED(CONFIG_USBC_DISABLE_CHARGE_FROM_RP_DEF) && charge == 500)
- charge = 0;
-
- if (cc_is_rp(cc_alt))
- charge |= TYPEC_CURRENT_DTS_MASK;
-
- return charge;
-}
-
-enum tcpc_cc_polarity get_snk_polarity(enum tcpc_cc_voltage_status cc1,
- enum tcpc_cc_voltage_status cc2)
-{
- /* The following assumes:
- *
- * TYPEC_CC_VOLT_RP_3_0 > TYPEC_CC_VOLT_RP_1_5
- * TYPEC_CC_VOLT_RP_1_5 > TYPEC_CC_VOLT_RP_DEF
- * TYPEC_CC_VOLT_RP_DEF > TYPEC_CC_VOLT_OPEN
- */
- if (cc_is_src_dbg_acc(cc1, cc2))
- return (cc1 > cc2) ? POLARITY_CC1_DTS : POLARITY_CC2_DTS;
-
- return (cc1 > cc2) ? POLARITY_CC1 : POLARITY_CC2;
-}
-
-enum tcpc_cc_polarity get_src_polarity(enum tcpc_cc_voltage_status cc1,
- enum tcpc_cc_voltage_status cc2)
-{
- return (cc1 == TYPEC_CC_VOLT_RD) ? POLARITY_CC1 : POLARITY_CC2;
-}
-
-enum pd_cc_states pd_get_cc_state(
- enum tcpc_cc_voltage_status cc1, enum tcpc_cc_voltage_status cc2)
-{
- /* Port partner is a SNK */
- if (cc_is_snk_dbg_acc(cc1, cc2))
- return PD_CC_UFP_DEBUG_ACC;
- if (cc_is_at_least_one_rd(cc1, cc2))
- return PD_CC_UFP_ATTACHED;
- if (cc_is_audio_acc(cc1, cc2))
- return PD_CC_UFP_AUDIO_ACC;
-
- /* Port partner is a SRC */
- if (cc_is_rp(cc1) && cc_is_rp(cc2))
- return PD_CC_DFP_DEBUG_ACC;
- if (cc_is_rp(cc1) || cc_is_rp(cc2))
- return PD_CC_DFP_ATTACHED;
-
- /*
- * 1) Both lines are Vopen or
- * 2) Only an e-marked cabled without a partner on the other side
- */
- return PD_CC_NONE;
-}
-
-/**
- * This function checks the current CC status of the port partner
- * and returns true if the attached partner is debug accessory.
- */
-bool pd_is_debug_acc(int port)
-{
- enum pd_cc_states cc_state = pd_get_task_cc_state(port);
-
- return cc_state == PD_CC_UFP_DEBUG_ACC ||
- cc_state == PD_CC_DFP_DEBUG_ACC;
-}
-
-void pd_set_polarity(int port, enum tcpc_cc_polarity polarity)
-{
- tcpm_set_polarity(port, polarity);
-
- if (IS_ENABLED(CONFIG_USBC_PPC_POLARITY))
- ppc_set_polarity(port, polarity);
-}
-
-__overridable int pd_board_check_request(uint32_t rdo, int pdo_cnt)
-{
- return EC_SUCCESS;
-}
-
-int pd_check_requested_voltage(uint32_t rdo, const int port)
-{
- int max_ma = rdo & 0x3FF;
- int op_ma = (rdo >> 10) & 0x3FF;
- int idx = RDO_POS(rdo);
- uint32_t pdo;
- uint32_t pdo_ma;
-#if defined(CONFIG_USB_PD_TCPMV2) && defined(CONFIG_USB_PE_SM)
- const uint32_t *src_pdo;
- const int pdo_cnt = dpm_get_source_pdo(&src_pdo, port);
-#elif defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \
- defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT)
- const uint32_t *src_pdo;
- const int pdo_cnt = charge_manager_get_source_pdo(&src_pdo, port);
-#else
- const uint32_t *src_pdo = pd_src_pdo;
- const int pdo_cnt = pd_src_pdo_cnt;
-#endif
-
- /* Check for invalid index */
- if (!idx || idx > pdo_cnt)
- return EC_ERROR_INVAL;
-
- /* Board specific check for this request */
- if (pd_board_check_request(rdo, pdo_cnt))
- return EC_ERROR_INVAL;
-
- /* check current ... */
- pdo = src_pdo[idx - 1];
- pdo_ma = (pdo & 0x3ff);
-
- if (op_ma > pdo_ma)
- return EC_ERROR_INVAL; /* too much op current */
-
- if (max_ma > pdo_ma && !(rdo & RDO_CAP_MISMATCH))
- return EC_ERROR_INVAL; /* too much max current */
-
- CPRINTF("Requested %d mV %d mA (for %d/%d mA)\n",
- ((pdo >> 10) & 0x3ff) * 50, (pdo & 0x3ff) * 10,
- op_ma * 10, max_ma * 10);
-
- /* Accept the requested voltage */
- return EC_SUCCESS;
-}
-
-__overridable uint8_t board_get_usb_pd_port_count(void)
-{
- return CONFIG_USB_PD_PORT_MAX_COUNT;
-}
-
-__overridable bool board_is_usb_pd_port_present(int port)
-{
- /*
- * Use board_get_usb_pd_port_count() instead of checking
- * CONFIG_USB_PD_PORT_MAX_COUNT directly here for legacy boards
- * that implement board_get_usb_pd_port_count() but do not
- * implement board_is_usb_pd_port_present().
- */
-
- return (port >= 0) && (port < board_get_usb_pd_port_count());
-}
-
-__overridable bool board_is_dts_port(int port)
-{
- return true;
-}
-
-int pd_get_retry_count(int port, enum tcpci_msg_type type)
-{
- /* PD 3.0 6.7.7: nRetryCount = 2; PD 2.0 6.6.9: nRetryCount = 3 */
- return pd_get_rev(port, type) == PD_REV30 ? 2 : 3;
-}
-
-enum pd_drp_next_states drp_auto_toggle_next_state(
- uint64_t *drp_sink_time,
- enum pd_power_role power_role,
- enum pd_dual_role_states drp_state,
- enum tcpc_cc_voltage_status cc1,
- enum tcpc_cc_voltage_status cc2,
- bool auto_toggle_supported)
-{
- const bool hardware_debounced_unattached =
- ((drp_state == PD_DRP_TOGGLE_ON) &&
- auto_toggle_supported);
-
- /* Set to appropriate port state */
- if (cc_is_open(cc1, cc2)) {
- /*
- * If nothing is attached then use drp_state to determine next
- * state. If DRP auto toggle is still on, then remain in the
- * DRP_AUTO_TOGGLE state. Otherwise, stop dual role toggling
- * and go to a disconnected state.
- */
- switch (drp_state) {
- case PD_DRP_TOGGLE_OFF:
- return DRP_TC_DEFAULT;
- case PD_DRP_FREEZE:
- if (power_role == PD_ROLE_SINK)
- return DRP_TC_UNATTACHED_SNK;
- else
- return DRP_TC_UNATTACHED_SRC;
- case PD_DRP_FORCE_SINK:
- return DRP_TC_UNATTACHED_SNK;
- case PD_DRP_FORCE_SOURCE:
- return DRP_TC_UNATTACHED_SRC;
- case PD_DRP_TOGGLE_ON:
- default:
- if (!auto_toggle_supported) {
- if (power_role == PD_ROLE_SINK)
- return DRP_TC_UNATTACHED_SNK;
- else
- return DRP_TC_UNATTACHED_SRC;
- }
-
- return DRP_TC_DRP_AUTO_TOGGLE;
- }
- } else if ((cc_is_rp(cc1) || cc_is_rp(cc2)) &&
- drp_state != PD_DRP_FORCE_SOURCE) {
- /* SNK allowed unless ForceSRC */
- if (hardware_debounced_unattached)
- return DRP_TC_ATTACHED_WAIT_SNK;
- return DRP_TC_UNATTACHED_SNK;
- } else if (cc_is_at_least_one_rd(cc1, cc2) ||
- cc_is_audio_acc(cc1, cc2)) {
- /*
- * SRC allowed unless ForceSNK or Toggle Off
- *
- * Ideally we wouldn't use auto-toggle when drp_state is
- * TOGGLE_OFF/FORCE_SINK, but for some TCPCs, auto-toggle can't
- * be prevented in low power mode. Try being a sink in case the
- * connected device is dual-role (this ensures reliable charging
- * from a hub, b/72007056). 100 ms is enough time for a
- * dual-role partner to switch from sink to source. If the
- * connected device is sink-only, then we will attempt
- * TC_UNATTACHED_SNK twice (due to debounce time), then return
- * to low power mode (and stay there). After 200 ms, reset
- * ready for a new connection.
- */
- if (drp_state == PD_DRP_TOGGLE_OFF ||
- drp_state == PD_DRP_FORCE_SINK) {
- if (get_time().val > *drp_sink_time + 200*MSEC)
- *drp_sink_time = get_time().val;
- if (get_time().val < *drp_sink_time + 100*MSEC)
- return DRP_TC_UNATTACHED_SNK;
- else
- return DRP_TC_DRP_AUTO_TOGGLE;
- } else {
- if (hardware_debounced_unattached)
- return DRP_TC_ATTACHED_WAIT_SRC;
- return DRP_TC_UNATTACHED_SRC;
- }
- } else {
- /* Anything else, keep toggling */
- if (!auto_toggle_supported) {
- if (power_role == PD_ROLE_SINK)
- return DRP_TC_UNATTACHED_SNK;
- else
- return DRP_TC_UNATTACHED_SRC;
- }
-
- return DRP_TC_DRP_AUTO_TOGGLE;
- }
-}
-
-__overridable bool usb_ufp_check_usb3_enable(int port)
-{
- return false;
-}
-
-mux_state_t get_mux_mode_to_set(int port)
-{
- /*
- * If the SoC is down, then we disconnect the MUX to save power since
- * no one cares about the data lines.
- */
- if (IS_ENABLED(CONFIG_POWER_COMMON) &&
- chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF))
- return USB_PD_MUX_NONE;
-
- /*
- * When PD stack is disconnected, then mux should be disconnected, which
- * is also what happens in the set_state disconnection code. Once the
- * PD state machine progresses out of disconnect, the MUX state will
- * be set correctly again.
- */
- if (pd_is_disconnected(port))
- return USB_PD_MUX_NONE;
-
- /*
- * For type-c only connections, there may be a need to enable USB3.1
- * mode when the port is in a UFP data role, independent of any other
- * conditions which are checked below. The default function returns
- * false, so only boards that override this check will be affected.
- */
- if (usb_ufp_check_usb3_enable(port) && pd_get_data_role(port)
- == PD_ROLE_UFP)
- return USB_PD_MUX_USB_ENABLED;
-
- /* If new data role isn't DFP & we only support DFP, also disconnect. */
- if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE) &&
- IS_ENABLED(CONFIG_USBC_SS_MUX_DFP_ONLY) &&
- pd_get_data_role(port) != PD_ROLE_DFP)
- return USB_PD_MUX_NONE;
-
- /* If new data role isn't UFP & we only support UFP then disconnect. */
- if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE) &&
- IS_ENABLED(CONFIG_USBC_SS_MUX_UFP_ONLY) &&
- pd_get_data_role(port) != PD_ROLE_UFP)
- return USB_PD_MUX_NONE;
-
- /*
- * If the power role is sink and the PD partner device is not capable
- * of USB communication then disconnect.
- *
- * On an entry into Unattached.SNK, the partner may be PD capable but
- * hasn't yet sent source capabilities. In this case, hold off enabling
- * USB3 termination until the PD capability is resolved.
- *
- * TODO(b/188588458): TCPMv2: Delay enabling USB3 termination when USB4
- * is supported.
- */
- if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE) &&
- pd_get_power_role(port) == PD_ROLE_SINK &&
- (pd_capable(port) || pd_waiting_on_partner_src_caps(port)) &&
- !pd_get_partner_usb_comm_capable(port))
- return USB_PD_MUX_NONE;
-
- /* Otherwise connect mux since we are in S3+ */
- return USB_PD_MUX_USB_ENABLED;
-}
-
-void set_usb_mux_with_current_data_role(int port)
-{
- if (IS_ENABLED(CONFIG_USBC_SS_MUX)) {
- mux_state_t mux_mode = get_mux_mode_to_set(port);
- enum usb_switch usb_switch_mode =
- (mux_mode == USB_PD_MUX_NONE) ?
- USB_SWITCH_DISCONNECT : USB_SWITCH_CONNECT;
-
- usb_mux_set(port, mux_mode, usb_switch_mode,
- polarity_rm_dts(pd_get_polarity(port)));
- }
-}
-
-void usb_mux_set_safe_mode(int port)
-{
- if (IS_ENABLED(CONFIG_USBC_SS_MUX)) {
- usb_mux_set(port, IS_ENABLED(CONFIG_USB_MUX_VIRTUAL) ?
- USB_PD_MUX_SAFE_MODE : USB_PD_MUX_NONE,
- USB_SWITCH_CONNECT,
- polarity_rm_dts(pd_get_polarity(port)));
- }
-
- /* Isolate the SBU lines. */
- if (IS_ENABLED(CONFIG_USBC_PPC_SBU))
- ppc_set_sbu(port, 0);
-}
-
-void usb_mux_set_safe_mode_exit(int port)
-{
- if (IS_ENABLED(CONFIG_USBC_SS_MUX))
- usb_mux_set(port, USB_PD_MUX_NONE, USB_SWITCH_CONNECT,
- polarity_rm_dts(pd_get_polarity(port)));
-
- /* Isolate the SBU lines. */
- if (IS_ENABLED(CONFIG_USBC_PPC_SBU))
- ppc_set_sbu(port, 0);
-}
-
-static void pd_send_hard_reset(int port)
-{
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SEND_HARD_RESET);
-}
-
-#ifdef CONFIG_USBC_OCP
-
-static uint32_t port_oc_reset_req;
-
-static void re_enable_ports(void)
-{
- uint32_t ports = atomic_clear(&port_oc_reset_req);
-
- while (ports) {
- int port = __fls(ports);
-
- ports &= ~BIT(port);
-
- /*
- * Let the board know that the overcurrent is
- * over since we're going to attempt re-enabling
- * the port.
- */
- board_overcurrent_event(port, 0);
-
- pd_send_hard_reset(port);
- /*
- * TODO(b/117854867): PD3.0 to send an alert message
- * indicating OCP after explicit contract.
- */
- }
-}
-DECLARE_DEFERRED(re_enable_ports);
-
-void pd_handle_overcurrent(int port)
-{
- if ((port < 0) || (port >= board_get_usb_pd_port_count())) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return;
- }
-
- CPRINTS("C%d: overcurrent!", port);
-
- if (IS_ENABLED(CONFIG_USB_PD_LOGGING))
- pd_log_event(PD_EVENT_PS_FAULT, PD_LOG_PORT_SIZE(port, 0),
- PS_FAULT_OCP, NULL);
-
- /* No action to take if disconnected, just log. */
- if (pd_is_disconnected(port))
- return;
-
- /* Keep track of the overcurrent events. */
- usbc_ocp_add_event(port);
-
- /* Let the board specific code know about the OC event. */
- board_overcurrent_event(port, 1);
-
- /* Wait 1s before trying to re-enable the port. */
- atomic_or(&port_oc_reset_req, BIT(port));
- hook_call_deferred(&re_enable_ports_data, SECOND);
-}
-
-#endif /* CONFIG_USBC_OCP */
-
-__maybe_unused void pd_handle_cc_overvoltage(int port)
-{
- pd_send_hard_reset(port);
-}
-
-__overridable int pd_board_checks(void)
-{
- return EC_SUCCESS;
-}
-
-__overridable int pd_check_data_swap(int port,
- enum pd_data_role data_role)
-{
- /* Allow data swap if we are a UFP, otherwise don't allow. */
- return (data_role == PD_ROLE_UFP) ? 1 : 0;
-}
-
-__overridable int pd_check_power_swap(int port)
-{
- /*
- * Allow power swap if we are acting as a dual role device. If we are
- * not acting as dual role (ex. suspended), then only allow power swap
- * if we are sourcing when we could be sinking.
- */
- if (pd_get_dual_role(port) == PD_DRP_TOGGLE_ON)
- return 1;
- else if (pd_get_power_role(port) == PD_ROLE_SOURCE)
- return 1;
-
- return 0;
-}
-
-__overridable void pd_execute_data_swap(int port,
- enum pd_data_role data_role)
-{
-}
-
-__overridable enum pd_dual_role_states pd_get_drp_state_in_suspend(void)
-{
- /* Disable dual role when going to suspend */
- return PD_DRP_TOGGLE_OFF;
-}
-
-__overridable void pd_try_execute_vconn_swap(int port, int flags)
-{
- /*
- * If partner is dual-role power and vconn swap is enabled, consider
- * if vconn swapping is necessary.
- */
- if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE) &&
- IS_ENABLED(CONFIG_USBC_VCONN_SWAP))
- pd_try_vconn_src(port);
-}
-
-__overridable int pd_is_valid_input_voltage(int mv)
-{
- return 1;
-}
-
-__overridable void pd_transition_voltage(int idx)
-{
- /* Most devices are fixed 5V output. */
-}
-
-__overridable void typec_set_source_current_limit(int p, enum tcpc_rp_value rp)
-{
- if (IS_ENABLED(CONFIG_USBC_PPC))
- ppc_set_vbus_source_current_limit(p, rp);
-}
-
-/* ---------------- Power Data Objects (PDOs) ----------------- */
-#ifndef CONFIG_USB_PD_CUSTOM_PDO
-#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\
- PDO_FIXED_COMM_CAP)
-
-const uint32_t pd_src_pdo[] = {
- PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS),
-};
-const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo);
-const uint32_t pd_src_pdo_max[] = {
- PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS),
-};
-const int pd_src_pdo_max_cnt = ARRAY_SIZE(pd_src_pdo_max);
-
-const uint32_t pd_snk_pdo[] = {
- PDO_FIXED(5000,
- GENERIC_MIN((PD_OPERATING_POWER_MW / 5), PD_MAX_CURRENT_MA),
- PDO_FIXED_FLAGS),
- PDO_BATT(4750, PD_MAX_VOLTAGE_MV, PD_OPERATING_POWER_MW),
- PDO_VAR(4750, PD_MAX_VOLTAGE_MV, PD_MAX_CURRENT_MA),
-};
-const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo);
-#endif /* CONFIG_USB_PD_CUSTOM_PDO */
-
-/* ----------------- Vendor Defined Messages ------------------ */
-#if defined(CONFIG_USB_PE_SM) && !defined(CONFIG_USB_VPD) && \
- !defined(CONFIG_USB_CTVPD)
-__overridable int pd_custom_vdm(int port, int cnt, uint32_t *payload,
- uint32_t **rpayload)
-{
- int cmd = PD_VDO_CMD(payload[0]);
- uint16_t dev_id = 0;
- int is_rw, is_latest;
-
- /* make sure we have some payload */
- if (cnt == 0)
- return 0;
-
- /* Only handle custom requests for SVID Google */
- if (PD_VDO_VID(*payload) != USB_VID_GOOGLE)
- return 0;
-
- switch (cmd) {
- case VDO_CMD_VERSION:
- /* guarantee last byte of payload is null character */
- *(payload + cnt - 1) = 0;
- CPRINTF("version: %s\n", (char *)(payload+1));
- break;
- case VDO_CMD_READ_INFO:
- case VDO_CMD_SEND_INFO:
- /* copy hash */
- if (cnt == 7) {
- dev_id = VDO_INFO_HW_DEV_ID(payload[6]);
- is_rw = VDO_INFO_IS_RW(payload[6]);
-
- is_latest = pd_dev_store_rw_hash(
- port, dev_id, payload + 1,
- is_rw ? EC_IMAGE_RW : EC_IMAGE_RO);
-
- /*
- * Send update host event unless our RW hash is
- * already known to be the latest update RW.
- */
- if (!is_rw || !is_latest)
- pd_send_host_event(PD_EVENT_UPDATE_DEVICE);
-
- CPRINTF("DevId:%d.%d SW:%d RW:%d\n",
- HW_DEV_ID_MAJ(dev_id),
- HW_DEV_ID_MIN(dev_id),
- VDO_INFO_SW_DBG_VER(payload[6]),
- is_rw);
- } else if (cnt == 6) {
- /* really old devices don't have last byte */
- pd_dev_store_rw_hash(port, dev_id, payload + 1,
- EC_IMAGE_UNKNOWN);
- }
- break;
- case VDO_CMD_CURRENT:
- CPRINTF("Current: %dmA\n", payload[1]);
- break;
- case VDO_CMD_FLIP:
- if (IS_ENABLED(CONFIG_USBC_SS_MUX))
- usb_mux_flip(port);
- break;
-#ifdef CONFIG_USB_PD_LOGGING
- case VDO_CMD_GET_LOG:
- pd_log_recv_vdm(port, cnt, payload);
- break;
-#endif /* CONFIG_USB_PD_LOGGING */
- }
-
- return 0;
-}
-#endif /* CONFIG_USB_PE_SM && !CONFIG_USB_VPD && !CONFIG_USB_CTVPD */
-
-__overridable bool vboot_allow_usb_pd(void)
-{
- return false;
-}
-
-/* VDM utility functions */
-static void pd_usb_billboard_deferred(void)
-{
- if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE) &&
- !IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP) &&
- !IS_ENABLED(CONFIG_USB_PD_SIMPLE_DFP) &&
- IS_ENABLED(CONFIG_USB_BOS)) {
- /*
- * TODO(tbroch)
- * 1. Will we have multiple type-C port UFPs
- * 2. Will there be other modes applicable to DFPs besides DP
- */
- if (!pd_alt_mode(0, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT))
- usb_connect();
- }
-}
-DECLARE_DEFERRED(pd_usb_billboard_deferred);
-
-#ifdef CONFIG_USB_PD_DISCHARGE
-static void gpio_discharge_vbus(int port, int enable)
-{
-#ifdef CONFIG_USB_PD_DISCHARGE_GPIO
- enum gpio_signal dischg_gpio[] = {
- GPIO_USB_C0_DISCHARGE,
-#if CONFIG_USB_PD_PORT_MAX_COUNT > 1
- GPIO_USB_C1_DISCHARGE,
-#endif
-#if CONFIG_USB_PD_PORT_MAX_COUNT > 2
- GPIO_USB_C2_DISCHARGE,
-#endif
- };
- BUILD_ASSERT(ARRAY_SIZE(dischg_gpio) == CONFIG_USB_PD_PORT_MAX_COUNT);
-
- gpio_set_level(dischg_gpio[port], enable);
-#endif /* CONFIG_USB_PD_DISCHARGE_GPIO */
-}
-
-void pd_set_vbus_discharge(int port, int enable)
-{
- static mutex_t discharge_lock[CONFIG_USB_PD_PORT_MAX_COUNT];
-#ifdef CONFIG_ZEPHYR
- static bool inited[CONFIG_USB_PD_PORT_MAX_COUNT];
-
- if (!inited[port]) {
- (void)k_mutex_init(&discharge_lock[port]);
- inited[port] = true;
- }
-#endif
- if (port >= board_get_usb_pd_port_count())
- return;
-
- mutex_lock(&discharge_lock[port]);
- enable &= !board_vbus_source_enabled(port);
-
- 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
- tcpc_discharge_vbus(port, enable);
-#endif
- } else if (get_usb_pd_discharge() == USB_PD_DISCHARGE_PPC) {
-#ifdef CONFIG_USB_PD_DISCHARGE_PPC
- ppc_discharge_vbus(port, enable);
-#endif
- }
-
- mutex_unlock(&discharge_lock[port]);
-}
-#endif /* CONFIG_USB_PD_DISCHARGE */
-
-#ifdef CONFIG_USB_PD_TCPM_TCPCI
-static uint32_t pd_ports_to_resume;
-static void resume_pd_port(void)
-{
- uint32_t port;
- uint32_t suspended_ports = atomic_clear(&pd_ports_to_resume);
-
- while (suspended_ports) {
- port = __builtin_ctz(suspended_ports);
- suspended_ports &= ~BIT(port);
- pd_set_suspend(port, 0);
- }
-}
-DECLARE_DEFERRED(resume_pd_port);
-
-void pd_deferred_resume(int port)
-{
- atomic_or(&pd_ports_to_resume, 1 << port);
- hook_call_deferred(&resume_pd_port_data, 5 * SECOND);
-}
-#endif /* CONFIG_USB_PD_TCPM_TCPCI */
-
-__overridable int pd_snk_is_vbus_provided(int port)
-{
- return EC_SUCCESS;
-}
-
-/*
- * Check the specified Vbus level
- *
- * Note that boards may override this function if they have a method outside the
- * TCPCI driver to verify vSafe0V.
- */
-__overridable bool pd_check_vbus_level(int port, enum vbus_level level)
-{
- if (IS_ENABLED(CONFIG_USB_PD_VBUS_DETECT_TCPC) &&
- (get_usb_pd_vbus_detect() == USB_PD_VBUS_DETECT_TCPC)) {
- return tcpm_check_vbus_level(port, level);
- }
- else if (level == VBUS_PRESENT)
- return pd_snk_is_vbus_provided(port);
- else
- return !pd_snk_is_vbus_provided(port);
-}
-
-int pd_is_vbus_present(int port)
-{
- return pd_check_vbus_level(port, VBUS_PRESENT);
-}
-
-#ifdef CONFIG_USB_PD_FRS
-__overridable int board_pd_set_frs_enable(int port, int enable)
-{
- return EC_SUCCESS;
-}
-
-int pd_set_frs_enable(int port, int enable)
-{
- int rv = EC_SUCCESS;
-
- if (IS_ENABLED(CONFIG_USB_PD_FRS_PPC))
- rv = ppc_set_frs_enable(port, enable);
- if (rv == EC_SUCCESS && IS_ENABLED(CONFIG_USB_PD_FRS_TCPC))
- rv = tcpm_set_frs_enable(port, enable);
- if (rv == EC_SUCCESS)
- rv = board_pd_set_frs_enable(port, enable);
- return rv;
-}
-#endif /* defined(CONFIG_USB_PD_FRS) */
-
-#ifdef CONFIG_CMD_TCPC_DUMP
-/*
- * Dump TCPC registers.
- */
-void tcpc_dump_registers(int port, const struct tcpc_reg_dump_map *reg,
- int count)
-{
- int i, val;
-
- for (i = 0; i < count; i++, reg++) {
- switch (reg->size) {
- case 1:
- tcpc_read(port, reg->addr, &val);
- ccprintf(" %-30s(0x%02x) = 0x%02x\n",
- reg->name, reg->addr, (uint8_t)val);
- break;
- case 2:
- tcpc_read16(port, reg->addr, &val);
- ccprintf(" %-30s(0x%02x) = 0x%04x\n",
- reg->name, reg->addr, (uint16_t)val);
- break;
- }
- cflush();
- }
-
-}
-
-static int command_tcpc_dump(int argc, char **argv)
-{
- int port;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- port = atoi(argv[1]);
- if ((port < 0) || (port >= board_get_usb_pd_port_count())) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
- /* Dump TCPC registers. */
- tcpm_dump_registers(port);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(tcpci_dump, command_tcpc_dump, "<Type-C port>",
- "dump the TCPC regs");
-#endif /* defined(CONFIG_CMD_TCPC_DUMP) */
-
-void pd_srccaps_dump(int port)
-{
- int i;
- const uint32_t *const srccaps = pd_get_src_caps(port);
-
- for (i = 0; i < pd_get_src_cap_cnt(port); ++i) {
- uint32_t max_ma, max_mv, min_mv;
-
- pd_extract_pdo_power(srccaps[i], &max_ma, &max_mv, &min_mv);
-
- if ((srccaps[i] & PDO_TYPE_MASK) == PDO_TYPE_AUGMENTED) {
- if (IS_ENABLED(CONFIG_USB_PD_REV30))
- ccprintf("%d: %dmV-%dmV/%dmA\n", i, min_mv,
- max_mv, max_ma);
- } else {
- ccprintf("%d: %dmV/%dmA\n", i, max_mv, max_ma);
- }
- }
-}
-
-int pd_build_alert_msg(uint32_t *msg, uint32_t *len, enum pd_power_role pr)
-{
- if (msg == NULL || len == NULL)
- return EC_ERROR_INVAL;
-
- /*
- * SOURCE: currently only supports OCP
- * SINK: currently only supports OVP
- */
- if (pr == PD_ROLE_SOURCE)
- *msg = ADO_OCP_EVENT;
- else
- *msg = ADO_OVP_EVENT;
-
- /* Alert data is 4 bytes */
- *len = 4;
-
- return EC_SUCCESS;
-}
diff --git a/common/usb_console_stream.c b/common/usb_console_stream.c
deleted file mode 100644
index 13dd7f8264..0000000000
--- a/common/usb_console_stream.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/* Copyright 2019 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.
- */
-
-#include "common.h"
-#include "config.h"
-#include "console.h"
-#include "crc.h"
-#include "link_defs.h"
-#include "printf.h"
-#include "queue.h"
-#include "task.h"
-#include "timer.h"
-#include "usb-stream.h"
-
-#ifdef CONFIG_USB_CONSOLE
-/*
- * CONFIG_USB_CONSOLE and CONFIG_USB_CONSOLE_STREAM should be defined
- * exclusively each other.
- */
-#error "Do not enable CONFIG_USB_CONSOLE."
-#endif
-
-/* Console output macro */
-#define USB_CONSOLE_TIMEOUT_US (30 * MSEC)
-
-#define QUEUE_SIZE_USB_TX CONFIG_USB_CONSOLE_TX_BUF_SIZE
-#define QUEUE_SIZE_USB_RX USB_MAX_PACKET_SIZE
-
-static void usb_console_wr(struct queue_policy const *policy, size_t count);
-static void uart_console_rd(struct queue_policy const *policy, size_t count);
-
-
-static int last_tx_ok = 1;
-
-/*
- * Start enabled, so we can queue early debug output before the board gets
- * around to calling usb_console_enable().
- */
-static int is_enabled = 1;
-
-/*
- * But start read-only, so we don't accept console input until we explicitly
- * decide that we're ready for it.
- */
-static int is_readonly = 1;
-
-/*
- * This is a usb_console producer policy, which wakes up CONSOLE task whenever
- * rx_q gets new data added. This shall be called by rx_stream_handler() in
- * usb-stream.c.
- */
-static struct queue_policy const usb_console_policy = {
- .add = usb_console_wr,
- .remove = uart_console_rd,
-};
-
-static struct queue const tx_q = QUEUE_NULL(QUEUE_SIZE_USB_TX, uint8_t);
-static struct queue const rx_q = QUEUE(QUEUE_SIZE_USB_RX, uint8_t,
- usb_console_policy);
-
-struct usb_stream_config const usb_console;
-
-USB_STREAM_CONFIG(usb_console,
- USB_IFACE_CONSOLE,
- USB_STR_CONSOLE_NAME,
- USB_EP_CONSOLE,
- USB_MAX_PACKET_SIZE,
- USB_MAX_PACKET_SIZE,
- rx_q,
- tx_q)
-
-static void usb_console_wr(struct queue_policy const *policy, size_t count)
-{
- console_has_input();
-}
-
-static void uart_console_rd(struct queue_policy const *policy, size_t count)
-{
- /* do nothing */
-}
-
-static void handle_output(void)
-{
- /* Wake up the Tx FIFO handler */
- usb_console.consumer.ops->written(&usb_console.consumer, 1);
-}
-
-static int usb_wait_console(void)
-{
- timestamp_t deadline = get_time();
- int wait_time_us = 1;
-
- if (!is_enabled || !tx_fifo_is_ready(&usb_console))
- return EC_SUCCESS;
-
- deadline.val += USB_CONSOLE_TIMEOUT_US;
-
- /*
- * If the USB console is not used, Tx buffer would never free up.
- * In this case, let's drop characters immediately instead of sitting
- * for some time just to time out. On the other hand, if the last
- * Tx is good, it's likely the host is there to receive data, and
- * we should wait so that we don't clobber the buffer.
- */
- if (last_tx_ok) {
- while (queue_space(&tx_q) < USB_MAX_PACKET_SIZE ||
- !*usb_console.is_reset) {
- if (timestamp_expired(deadline, NULL) ||
- in_interrupt_context()) {
- last_tx_ok = 0;
- return EC_ERROR_TIMEOUT;
- }
- if (wait_time_us < MSEC)
- udelay(wait_time_us);
- else
- usleep(wait_time_us);
- wait_time_us *= 2;
- }
- } else {
- last_tx_ok = queue_space(&tx_q);
- }
-
- return EC_SUCCESS;
-}
-
-#ifdef CONFIG_USB_CONSOLE_CRC
-static uint32_t usb_tx_crc_ctx;
-
-void usb_console_crc_init(void)
-{
- crc32_ctx_init(&usb_tx_crc_ctx);
-}
-
-uint32_t usb_console_crc(void)
-{
- return crc32_ctx_result(&usb_tx_crc_ctx);
-}
-#endif
-
-static int __tx_char(void *context, int c)
-{
- int ret;
-
- if (c == '\n') {
- ret = __tx_char(NULL, '\r');
- if (ret)
- return ret;
- }
-
-#ifdef CONFIG_USB_CONSOLE_CRC
- crc32_ctx_hash8(&usb_tx_crc_ctx, c);
-
- while (queue_add_unit(&tx_q, &c) != 1)
- usleep(500);
-
- return EC_SUCCESS;
-#else
- /* Return 0 on success */
- return queue_add_unit(&tx_q, &c) ? EC_SUCCESS : EC_ERROR_OVERFLOW;
-#endif
-}
-
-/*
- * Public USB console implementation below.
- */
-int usb_getc(void)
-{
- int c;
-
- if (is_readonly || !is_enabled)
- return -1;
-
- if (!queue_remove_unit(&rx_q, &c))
- return -1;
-
- return c;
-}
-
-int usb_puts(const char *outstr)
-{
- int ret;
-
- if (!is_enabled)
- return EC_SUCCESS;
-
- ret = usb_wait_console();
- if (ret)
- return ret;
-
- while (*outstr) {
- ret = __tx_char(NULL, *outstr++);
- if (ret)
- break;
- }
- handle_output();
-
- return ret;
-}
-
-int usb_putc(int c)
-{
- static char string[2] = { 0, '\0' };
-
- string[0] = c;
-
- return usb_puts(string);
-}
-
-int usb_vprintf(const char *format, va_list args)
-{
- int ret;
-
- if (!is_enabled)
- return EC_SUCCESS;
-
- ret = usb_wait_console();
- if (ret)
- return ret;
-
- ret = vfnprintf(__tx_char, NULL, format, args);
-
- handle_output();
-
- return ret;
-}
-
-void usb_console_enable(int enabled, int readonly)
-{
- is_enabled = enabled;
- is_readonly = readonly;
-}
-
-int usb_console_tx_blocked(void)
-{
- return is_enabled && (queue_space(&tx_q) < USB_MAX_PACKET_SIZE);
-}
diff --git a/common/usb_i2c.c b/common/usb_i2c.c
deleted file mode 100644
index ace2e7139c..0000000000
--- a/common/usb_i2c.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/* Copyright 2016 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.
- */
-
-#include "common.h"
-#include "link_defs.h"
-#include "registers.h"
-#include "i2c.h"
-#include "usb_descriptor.h"
-#include "util.h"
-
-#include "common.h"
-#include "console.h"
-#include "consumer.h"
-#include "producer.h"
-#include "queue.h"
-#include "queue_policies.h"
-#include "task.h"
-#include "usb-stream.h"
-#include "usb_i2c.h"
-
-
-#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args)
-
-
-USB_I2C_CONFIG(i2c,
- USB_IFACE_I2C,
- USB_STR_I2C_NAME,
- USB_EP_I2C)
-
-static int (*cros_cmd_handler)(void *data_in,
- size_t in_size,
- void *data_out,
- size_t out_size);
-
-static int16_t usb_i2c_map_error(int error)
-{
- switch (error) {
- case EC_SUCCESS: return USB_I2C_SUCCESS;
- case EC_ERROR_TIMEOUT: return USB_I2C_TIMEOUT;
- case EC_ERROR_BUSY: return USB_I2C_BUSY;
- default: return USB_I2C_UNKNOWN_ERROR | (error & 0x7fff);
- }
-}
-
-/*
- * Return value should be large enough to accommodate the entire read queue
- * buffer size. Let's use 4 bytes in case future designs have a lot of RAM and
- * allow for large buffers.
- */
-static uint32_t usb_i2c_read_packet(struct usb_i2c_config const *config)
-{
- return QUEUE_REMOVE_UNITS(config->consumer.queue, config->buffer,
- queue_count(config->consumer.queue));
-}
-
-static void usb_i2c_write_packet(struct usb_i2c_config const *config,
- size_t count)
-{
- QUEUE_ADD_UNITS(config->tx_queue, config->buffer, count);
-}
-
-static uint8_t usb_i2c_executable(struct usb_i2c_config const *config)
-{
- static size_t expected_size;
-
- if (!expected_size) {
- uint8_t peek[4];
-
- /*
- * In order to support larger write payload, we need to peek
- * the queue to see if we need to wait for more data.
- */
- if (queue_peek_units(config->consumer.queue,
- peek, 0, sizeof(peek))
- != sizeof(peek)) {
- /* Not enough data to calculate expected_size. */
- return 0;
- }
- /*
- * The first four bytes of the packet will describe its
- * expected size.
- */
- /* Header bytes and extra rc bytes, if present. */
- if (peek[3] & 0x80)
- expected_size = 6;
- else
- expected_size = 4;
-
- /* write count */
- expected_size += (((size_t)peek[0] & 0xf0) << 4) | peek[2];
- }
-
-
- if (queue_count(config->consumer.queue) >= expected_size) {
- expected_size = 0;
- return 1;
- }
-
- return 0;
-}
-
-static void usb_i2c_execute(struct usb_i2c_config const *config)
-{
- /* Payload is ready to execute. */
- uint32_t count = usb_i2c_read_packet(config);
- int portindex = (config->buffer[0] >> 0) & 0xf;
- uint16_t addr_flags = (config->buffer[0] >> 8) & 0x7f;
- int write_count = ((config->buffer[0] << 4) & 0xf00) |
- ((config->buffer[1] >> 0) & 0xff);
- int read_count = (config->buffer[1] >> 8) & 0xff;
- int offset = 0; /* Offset for extended reading header. */
-
- config->buffer[0] = 0;
- config->buffer[1] = 0;
-
- if (read_count & 0x80) {
- read_count = ((config->buffer[2] & 0xff) << 7) |
- (read_count & 0x7f);
- offset = 2;
- }
-
- if (!count || (!read_count && !write_count))
- return;
-
- if (!usb_i2c_board_is_enabled()) {
- config->buffer[0] = USB_I2C_DISABLED;
- } else if (write_count > CONFIG_USB_I2C_MAX_WRITE_COUNT ||
- write_count != (count - 4 - offset)) {
- config->buffer[0] = USB_I2C_WRITE_COUNT_INVALID;
- } else if (read_count > CONFIG_USB_I2C_MAX_READ_COUNT) {
- config->buffer[0] = USB_I2C_READ_COUNT_INVALID;
- } else if (portindex >= i2c_ports_used) {
- config->buffer[0] = USB_I2C_PORT_INVALID;
- } else if (addr_flags == USB_I2C_CMD_ADDR_FLAGS) {
- /*
- * This is a non-i2c command, invoke the handler if it has
- * been registered, if not - report the appropriate error.
- */
- if (!cros_cmd_handler)
- config->buffer[0] = USB_I2C_MISSING_HANDLER;
- else
- config->buffer[0] = cros_cmd_handler(config->buffer + 2,
- write_count,
- config->buffer + 2,
- read_count);
- } else {
- int ret;
-
- /*
- * TODO (crbug.com/750397): Add security. This currently
- * blindly passes through ALL I2C commands on any bus the EC
- * knows about. It should behave closer to
- * EC_CMD_I2C_PASSTHRU, which can protect ports and ranges.
- */
- ret = i2c_xfer(i2c_ports[portindex].port, addr_flags,
- (uint8_t *)(config->buffer + 2) + offset,
- write_count,
- (uint8_t *)(config->buffer + 2),
- read_count);
- config->buffer[0] = usb_i2c_map_error(ret);
- }
- usb_i2c_write_packet(config, read_count + 4);
-}
-
-void usb_i2c_deferred(struct usb_i2c_config const *config)
-{
- /* Check if we can proceed the queue. */
- if (usb_i2c_executable(config))
- usb_i2c_execute(config);
-}
-
-static void usb_i2c_written(struct consumer const *consumer, size_t count)
-{
- struct usb_i2c_config const *config =
- DOWNCAST(consumer, struct usb_i2c_config, consumer);
-
- hook_call_deferred(config->deferred, 0);
-}
-
-struct consumer_ops const usb_i2c_consumer_ops = {
- .written = usb_i2c_written,
-};
-
-int usb_i2c_register_cros_cmd_handler(int (*cmd_handler)
- (void *data_in,
- size_t in_size,
- void *data_out,
- size_t out_size))
-{
- if (cros_cmd_handler)
- return -1;
- cros_cmd_handler = cmd_handler;
- return 0;
-}
diff --git a/common/usb_pd_alt_mode_dfp.c b/common/usb_pd_alt_mode_dfp.c
deleted file mode 100644
index d7048f4c8e..0000000000
--- a/common/usb_pd_alt_mode_dfp.c
+++ /dev/null
@@ -1,1543 +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.
- *
- * Alternate Mode Downstream Facing Port (DFP) USB-PD module.
- */
-
-#include "chipset.h"
-#include "console.h"
-#include "task.h"
-#include "task_id.h"
-#include "timer.h"
-#include "usb_common.h"
-#include "usb_charge.h"
-#include "usb_dp_alt_mode.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
-#include "usb_tbt_alt_mode.h"
-#include "usbc_ppc.h"
-#include "util.h"
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#else
-#define CPRINTS(format, args...)
-#define CPRINTF(format, args...)
-#endif
-
-#ifndef PORT_TO_HPD
-#define PORT_TO_HPD(port) ((port) ? GPIO_USB_C1_DP_HPD : GPIO_USB_C0_DP_HPD)
-#endif /* PORT_TO_HPD */
-
-/* Tracker for which task is waiting on sysjump prep to finish */
-static volatile task_id_t sysjump_task_waiting = TASK_ID_INVALID;
-
-/*
- * timestamp of the next possible toggle to ensure the 2-ms spacing
- * between IRQ_HPD. Since this is used in overridable functions, this
- * has to be global.
- */
-uint64_t svdm_hpd_deadline[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-int dp_flags[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-uint32_t dp_status[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Console command multi-function preference set for a PD port. */
-
-__maybe_unused bool dp_port_mf_allow[CONFIG_USB_PD_PORT_MAX_COUNT] = {
- [0 ... CONFIG_USB_PD_PORT_MAX_COUNT - 1] = true};
-
-
-__overridable const struct svdm_response svdm_rsp = {
- .identity = NULL,
- .svids = NULL,
- .modes = NULL,
-};
-
-static int pd_get_mode_idx(int port, enum tcpci_msg_type type,
- uint16_t svid)
-{
- int amode_idx;
- struct partner_active_modes *active =
- pd_get_partner_active_modes(port, type);
-
- for (amode_idx = 0; amode_idx < PD_AMODE_COUNT; amode_idx++) {
- if (active->amodes[amode_idx].fx &&
- (active->amodes[amode_idx].fx->svid == svid))
- return amode_idx;
- }
- return -1;
-}
-
-static int pd_allocate_mode(int port, enum tcpci_msg_type type,
- uint16_t svid)
-{
- int i, j;
- struct svdm_amode_data *modep;
- int mode_idx = pd_get_mode_idx(port, type, svid);
- const struct pd_discovery *disc = pd_get_am_discovery(port, type);
- struct partner_active_modes *active =
- pd_get_partner_active_modes(port, type);
- assert(active);
-
- if (mode_idx != -1)
- return mode_idx;
-
- /* There's no space to enter another mode */
- if (active->amode_idx == PD_AMODE_COUNT) {
- CPRINTF("ERR:NO AMODE SPACE\n");
- return -1;
- }
-
- /* Allocate ... if SVID == 0 enter default supported policy */
- for (i = 0; i < supported_modes_cnt; i++) {
- for (j = 0; j < disc->svid_cnt; j++) {
- const struct svid_mode_data *svidp = &disc->svids[j];
-
- /*
- * Looking for a match between supported_modes and
- * discovered SVIDs; must also match the passed-in SVID
- * if that was non-zero. Otherwise, go to the next
- * discovered SVID.
- * TODO(b/155890173): Support AP-directed mode entry
- * where the mode is unknown to the TCPM.
- */
- if ((svidp->svid != supported_modes[i].svid) ||
- (svid && (svidp->svid != svid)))
- continue;
-
- modep = &active->amodes[active->amode_idx];
- modep->fx = &supported_modes[i];
- modep->data = &disc->svids[j];
- active->amode_idx++;
- return active->amode_idx - 1;
- }
- }
- return -1;
-}
-
-static int validate_mode_request(struct svdm_amode_data *modep,
- uint16_t svid, int opos)
-{
- if (!modep->fx)
- return 0;
-
- if (svid != modep->fx->svid) {
- CPRINTF("ERR:svid r:0x%04x != c:0x%04x\n",
- svid, modep->fx->svid);
- return 0;
- }
-
- if (opos != modep->opos) {
- CPRINTF("ERR:opos r:%d != c:%d\n",
- opos, modep->opos);
- return 0;
- }
-
- return 1;
-}
-
-void pd_prepare_sysjump(void)
-{
- int i;
-
- /* Exit modes before sysjump so we can cleanly enter again later */
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- /*
- * If the port is not capable of Alternate mode no need to
- * send the event.
- */
- if (!pd_alt_mode_capable(i))
- continue;
-
- sysjump_task_waiting = task_get_current();
- task_set_event(PD_PORT_TO_TASK_ID(i), PD_EVENT_SYSJUMP);
- task_wait_event_mask(TASK_EVENT_SYSJUMP_READY, -1);
- sysjump_task_waiting = TASK_ID_INVALID;
- }
-}
-
-/*
- * This algorithm defaults to choosing higher pin config over lower ones in
- * order to prefer multi-function if desired.
- *
- * NAME | SIGNALING | OUTPUT TYPE | MULTI-FUNCTION | PIN CONFIG
- * -------------------------------------------------------------
- * A | USB G2 | ? | no | 00_0001
- * B | USB G2 | ? | yes | 00_0010
- * C | DP | CONVERTED | no | 00_0100
- * D | PD | CONVERTED | yes | 00_1000
- * E | DP | DP | no | 01_0000
- * F | PD | DP | yes | 10_0000
- *
- * if UFP has NOT asserted multi-function preferred code masks away B/D/F
- * leaving only A/C/E. For single-output dongles that should leave only one
- * possible pin config depending on whether its a converter DP->(VGA|HDMI) or DP
- * output. If UFP is a USB-C receptacle it may assert C/D/E/F. The DFP USB-C
- * receptacle must always choose C/D in those cases.
- */
-int pd_dfp_dp_get_pin_mode(int port, uint32_t status)
-{
- struct svdm_amode_data *modep =
- pd_get_amode_data(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT);
- uint32_t mode_caps;
- uint32_t pin_caps;
- int mf_pref;
-
- /*
- * Default dp_port_mf_allow is true, we allow mf operation
- * if UFP_D supports it.
- */
-
- if (IS_ENABLED(CONFIG_CMD_MFALLOW))
- mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]) &&
- dp_port_mf_allow[port];
- else
- mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]);
-
- if (!modep)
- return 0;
-
- mode_caps = modep->data->mode_vdo[modep->opos - 1];
-
- /* TODO(crosbug.com/p/39656) revisit with DFP that can be a sink */
- pin_caps = PD_DP_PIN_CAPS(mode_caps);
-
- /* if don't want multi-function then ignore those pin configs */
- if (!mf_pref)
- pin_caps &= ~MODE_DP_PIN_MF_MASK;
-
- /* TODO(crosbug.com/p/39656) revisit if DFP drives USB Gen 2 signals */
- pin_caps &= ~MODE_DP_PIN_BR2_MASK;
-
- /* if C/D present they have precedence over E/F for USB-C->USB-C */
- if (pin_caps & (MODE_DP_PIN_C | MODE_DP_PIN_D))
- pin_caps &= ~(MODE_DP_PIN_E | MODE_DP_PIN_F);
-
- /* get_next_bit returns undefined for zero */
- if (!pin_caps)
- return 0;
-
- return 1 << get_next_bit(&pin_caps);
-}
-
-struct svdm_amode_data *pd_get_amode_data(int port,
- enum tcpci_msg_type type, uint16_t svid)
-{
- int idx = pd_get_mode_idx(port, type, svid);
- struct partner_active_modes *active =
- pd_get_partner_active_modes(port, type);
- assert(active);
-
- return (idx == -1) ? NULL : &active->amodes[idx];
-}
-
-/*
- * Enter default mode ( payload[0] == 0 ) or attempt to enter mode via svid &
- * opos
- */
-uint32_t pd_dfp_enter_mode(int port, enum tcpci_msg_type type,
- uint16_t svid, int opos)
-{
- int mode_idx = pd_allocate_mode(port, type, svid);
- struct svdm_amode_data *modep;
- uint32_t mode_caps;
-
- if (mode_idx == -1)
- return 0;
- modep = &pd_get_partner_active_modes(port, type)->amodes[mode_idx];
-
- if (!opos) {
- /* choose the lowest as default */
- modep->opos = 1;
- } else if (opos <= modep->data->mode_cnt) {
- modep->opos = opos;
- } else {
- CPRINTS("C%d: Invalid opos %d for SVID %x", port, opos, svid);
- return 0;
- }
-
- mode_caps = modep->data->mode_vdo[modep->opos - 1];
- if (modep->fx->enter(port, mode_caps) == -1)
- return 0;
-
- /*
- * Strictly speaking, this should only happen when the request
- * has been ACKed.
- * For TCPMV1, still set modal flag pre-emptively. For TCPMv2, the modal
- * flag is set when the ENTER command is ACK'd for each alt mode that is
- * supported.
- */
- if (IS_ENABLED(CONFIG_USB_PD_TCPMV1))
- pd_set_dfp_enter_mode_flag(port, true);
-
- /* SVDM to send to UFP for mode entry */
- return VDO(modep->fx->svid, 1, CMD_ENTER_MODE | VDO_OPOS(modep->opos));
-}
-
-/* TODO(b/170372521) : Incorporate exit mode specific changes to DPM SM */
-int pd_dfp_exit_mode(int port, enum tcpci_msg_type type, uint16_t svid,
- int opos)
-{
- struct svdm_amode_data *modep;
- struct partner_active_modes *active =
- pd_get_partner_active_modes(port, type);
- int idx;
-
- /*
- * Empty svid signals we should reset DFP VDM state by exiting all
- * entered modes then clearing state. This occurs when we've
- * disconnected or for hard reset.
- */
- if (!svid) {
- for (idx = 0; idx < PD_AMODE_COUNT; idx++)
- if (active->amodes[idx].fx)
- active->amodes[idx].fx->exit(port);
-
- pd_dfp_mode_init(port);
- return 0;
- }
-
- /*
- * TODO(crosbug.com/p/33946) : below needs revisited to allow multiple
- * mode exit. Additionally it should honor OPOS == 7 as DFP's request
- * to exit all modes. We currently don't have any UFPs that support
- * multiple modes on one SVID.
- */
- modep = pd_get_amode_data(port, type, svid);
- if (!modep || !validate_mode_request(modep, svid, opos))
- return 0;
-
- /* call DFPs exit function */
- modep->fx->exit(port);
-
- pd_set_dfp_enter_mode_flag(port, false);
-
- /* exit the mode */
- modep->opos = 0;
- return 1;
-}
-
-/*
- * Check if the SVID has been recorded previously. Some peripherals provide
- * duplicated SVID.
- */
-static bool is_svid_duplicated(const struct pd_discovery *disc, uint16_t svid)
-{
- int i;
-
- for (i = 0; i < disc->svid_cnt; ++i)
- if (disc->svids[i].svid == svid) {
- CPRINTF("ERR:SVIDDUP\n");
- return true;
- }
-
- return false;
-}
-
-void dfp_consume_attention(int port, uint32_t *payload)
-{
- uint16_t svid = PD_VDO_VID(payload[0]);
- int opos = PD_VDO_OPOS(payload[0]);
- struct svdm_amode_data *modep =
- pd_get_amode_data(port, TCPCI_MSG_SOP, svid);
-
- if (!modep || !validate_mode_request(modep, svid, opos))
- return;
-
- if (modep->fx->attention)
- modep->fx->attention(port, payload);
-}
-
-void dfp_consume_identity(int port, enum tcpci_msg_type type, int cnt,
- uint32_t *payload)
-{
- int ptype;
- struct pd_discovery *disc;
- size_t identity_size;
-
- if (type == TCPCI_MSG_SOP_PRIME &&
- !IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) {
- CPRINTF("ERR:Unexpected cable response\n");
- return;
- }
-
- ptype = PD_IDH_PTYPE(payload[VDO_I(IDH)]);
- disc = pd_get_am_discovery_and_notify_access(port, type);
- identity_size = MIN(sizeof(union disc_ident_ack),
- (cnt - 1) * sizeof(uint32_t));
-
- /* Note: only store VDOs, not the VDM header */
- memcpy(disc->identity.raw_value, payload + 1, identity_size);
- disc->identity_cnt = identity_size / sizeof(uint32_t);
-
- switch (ptype) {
- case IDH_PTYPE_AMA:
- /* Leave vbus ON if the following macro is false */
- if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE) &&
- IS_ENABLED(CONFIG_USBC_VCONN_SWAP)) {
- /* Adapter is requesting vconn, try to supply it */
- if (PD_VDO_AMA_VCONN_REQ(payload[VDO_I(AMA)]))
- pd_try_vconn_src(port);
-
- /* Only disable vbus if vconn was requested */
- if (PD_VDO_AMA_VCONN_REQ(payload[VDO_I(AMA)]) &&
- !PD_VDO_AMA_VBUS_REQ(payload[VDO_I(AMA)]))
- pd_power_supply_reset(port);
- }
- break;
- default:
- break;
- }
- pd_set_identity_discovery(port, type, PD_DISC_COMPLETE);
-}
-
-void dfp_consume_svids(int port, enum tcpci_msg_type type, int cnt,
- uint32_t *payload)
-{
- int i;
- uint32_t *ptr = payload + 1;
- int vdo = 1;
- uint16_t svid0, svid1;
- struct pd_discovery *disc =
- pd_get_am_discovery_and_notify_access(port, type);
-
- for (i = disc->svid_cnt; i < disc->svid_cnt + 12; i += 2) {
- if (i >= SVID_DISCOVERY_MAX) {
- CPRINTF("ERR:SVIDCNT\n");
- break;
- }
- /*
- * Verify we're still within the valid packet (count will be one
- * for the VDM header + xVDOs)
- */
- if (vdo >= cnt)
- break;
-
- svid0 = PD_VDO_SVID_SVID0(*ptr);
- if (!svid0)
- break;
-
- if (!is_svid_duplicated(disc, svid0))
- disc->svids[disc->svid_cnt++].svid = svid0;
-
- svid1 = PD_VDO_SVID_SVID1(*ptr);
- if (!svid1)
- break;
-
- if (!is_svid_duplicated(disc, svid1))
- disc->svids[disc->svid_cnt++].svid = svid1;
-
- ptr++;
- vdo++;
- }
- /* TODO(tbroch) need to re-issue discover svids if > 12 */
- if (i && ((i % 12) == 0))
- CPRINTF("ERR:SVID+12\n");
-
- pd_set_svids_discovery(port, type, PD_DISC_COMPLETE);
-}
-
-void dfp_consume_modes(int port, enum tcpci_msg_type type, int cnt,
- uint32_t *payload)
-{
- int svid_idx;
- struct svid_mode_data *mode_discovery = NULL;
- struct pd_discovery *disc =
- pd_get_am_discovery_and_notify_access(port, type);
- uint16_t response_svid = (uint16_t) PD_VDO_VID(payload[0]);
-
- for (svid_idx = 0; svid_idx < disc->svid_cnt; ++svid_idx) {
- uint16_t svid = disc->svids[svid_idx].svid;
-
- if (svid == response_svid) {
- mode_discovery = &disc->svids[svid_idx];
- break;
- }
- }
- if (!mode_discovery) {
- const struct svid_mode_data *requested_mode_data =
- pd_get_next_mode(port, type);
- CPRINTF("C%d: Mode response for undiscovered SVID %x, but TCPM "
- "requested SVID %x\n",
- port, response_svid, requested_mode_data->svid);
- /*
- * Although SVIDs discovery seemed like it succeeded before, the
- * partner is now responding with undiscovered SVIDs. Discovery
- * cannot reasonably continue under these circumstances.
- */
- pd_set_modes_discovery(port, type, requested_mode_data->svid,
- PD_DISC_FAIL);
- return;
- }
-
- mode_discovery->mode_cnt = cnt - 1;
- if (mode_discovery->mode_cnt < 1) {
- CPRINTF("ERR:NOMODE\n");
- pd_set_modes_discovery(port, type, mode_discovery->svid,
- PD_DISC_FAIL);
- return;
- }
-
- memcpy(mode_discovery->mode_vdo, &payload[1],
- sizeof(uint32_t) * mode_discovery->mode_cnt);
- disc->svid_idx++;
- pd_set_modes_discovery(port, type, mode_discovery->svid,
- PD_DISC_COMPLETE);
-}
-
-int pd_alt_mode(int port, enum tcpci_msg_type type, uint16_t svid)
-{
- struct svdm_amode_data *modep = pd_get_amode_data(port, type, svid);
-
- return (modep) ? modep->opos : -1;
-}
-
-void pd_set_identity_discovery(int port, enum tcpci_msg_type type,
- enum pd_discovery_state disc)
-{
- struct pd_discovery *pd =
- pd_get_am_discovery_and_notify_access(port, type);
-
- pd->identity_discovery = disc;
-}
-
-enum pd_discovery_state pd_get_identity_discovery(int port,
- enum tcpci_msg_type type)
-{
- const struct pd_discovery *disc = pd_get_am_discovery(port, type);
-
- return disc->identity_discovery;
-}
-
-const union disc_ident_ack *pd_get_identity_response(int port,
- enum tcpci_msg_type type)
-{
- if (type >= DISCOVERY_TYPE_COUNT)
- return NULL;
-
- return &pd_get_am_discovery(port, type)->identity;
-}
-
-uint16_t pd_get_identity_vid(int port)
-{
- const union disc_ident_ack *resp = pd_get_identity_response(port,
- TCPCI_MSG_SOP);
-
- return resp->idh.usb_vendor_id;
-}
-
-uint16_t pd_get_identity_pid(int port)
-{
- const union disc_ident_ack *resp = pd_get_identity_response(port,
- TCPCI_MSG_SOP);
-
- return resp->product.product_id;
-}
-
-uint8_t pd_get_product_type(int port)
-{
- const union disc_ident_ack *resp = pd_get_identity_response(port,
- TCPCI_MSG_SOP);
-
- return resp->idh.product_type;
-}
-
-void pd_set_svids_discovery(int port, enum tcpci_msg_type type,
- enum pd_discovery_state disc)
-{
- struct pd_discovery *pd =
- pd_get_am_discovery_and_notify_access(port, type);
-
- pd->svids_discovery = disc;
-}
-
-enum pd_discovery_state pd_get_svids_discovery(int port,
- enum tcpci_msg_type type)
-{
- const struct pd_discovery *disc = pd_get_am_discovery(port, type);
-
- return disc->svids_discovery;
-}
-
-int pd_get_svid_count(int port, enum tcpci_msg_type type)
-{
- const struct pd_discovery *disc = pd_get_am_discovery(port, type);
-
- return disc->svid_cnt;
-}
-
-uint16_t pd_get_svid(int port, uint16_t svid_idx, enum tcpci_msg_type type)
-{
- const struct pd_discovery *disc = pd_get_am_discovery(port, type);
-
- return disc->svids[svid_idx].svid;
-}
-
-void pd_set_modes_discovery(int port, enum tcpci_msg_type type,
- uint16_t svid, enum pd_discovery_state disc)
-{
- struct pd_discovery *pd =
- pd_get_am_discovery_and_notify_access(port, type);
- int svid_idx;
-
- for (svid_idx = 0; svid_idx < pd->svid_cnt; ++svid_idx) {
- struct svid_mode_data *mode_data = &pd->svids[svid_idx];
-
- if (mode_data->svid != svid)
- continue;
-
- mode_data->discovery = disc;
- return;
- }
-}
-
-enum pd_discovery_state pd_get_modes_discovery(int port,
- enum tcpci_msg_type type)
-{
- const struct svid_mode_data *mode_data = pd_get_next_mode(port, type);
-
- /*
- * If there are no SVIDs for which to discover modes, mode discovery is
- * trivially complete.
- */
- if (!mode_data)
- return PD_DISC_COMPLETE;
-
- return mode_data->discovery;
-}
-
-int pd_get_mode_vdo_for_svid(int port, enum tcpci_msg_type type,
- uint16_t svid, uint32_t *vdo_out)
-{
- int idx;
- const struct pd_discovery *disc;
-
- if (type >= DISCOVERY_TYPE_COUNT)
- return 0;
-
- disc = pd_get_am_discovery(port, type);
-
- for (idx = 0; idx < disc->svid_cnt; ++idx) {
- if (pd_get_svid(port, idx, type) == svid) {
- memcpy(vdo_out, disc->svids[idx].mode_vdo,
- sizeof(uint32_t) * disc->svids[idx].mode_cnt);
- return disc->svids[idx].mode_cnt;
- }
- }
- return 0;
-}
-
-const struct svid_mode_data *pd_get_next_mode(int port,
- enum tcpci_msg_type type)
-{
- const struct pd_discovery *disc = pd_get_am_discovery(port, type);
- const struct svid_mode_data *failed_mode_data = NULL;
- bool svid_good_discovery = false;
- int svid_idx;
-
- /* Walk through all of the discovery mode entries */
- for (svid_idx = 0; svid_idx < disc->svid_cnt; ++svid_idx) {
- const struct svid_mode_data *mode_data = &disc->svids[svid_idx];
-
- /* Discovery is needed, so send this one back now */
- if (mode_data->discovery == PD_DISC_NEEDED)
- return mode_data;
-
- /* Discovery already succeeded, save that it was seen */
- if (mode_data->discovery == PD_DISC_COMPLETE)
- svid_good_discovery = true;
- /* Discovery already failed, save first failure */
- else if (!failed_mode_data)
- failed_mode_data = mode_data;
- }
-
- /* If no good entries were located, then return last failed */
- if (!svid_good_discovery)
- return failed_mode_data;
-
- /*
- * Mode discovery has been attempted for every discovered SVID (if
- * any exist)
- */
- return NULL;
-}
-
-const uint32_t *pd_get_mode_vdo(int port, uint16_t svid_idx,
- enum tcpci_msg_type type)
-{
- const struct pd_discovery *disc = pd_get_am_discovery(port, type);
-
- return disc->svids[svid_idx].mode_vdo;
-}
-
-bool pd_is_mode_discovered_for_svid(int port, enum tcpci_msg_type type,
- uint16_t svid)
-{
- const struct pd_discovery *disc = pd_get_am_discovery(port, type);
- const struct svid_mode_data *mode_data;
-
- for (mode_data = disc->svids; mode_data < disc->svids + disc->svid_cnt;
- ++mode_data) {
- if (mode_data->svid == svid &&
- mode_data->discovery == PD_DISC_COMPLETE)
- return true;
- }
-
- return false;
-}
-
-void notify_sysjump_ready(void)
-{
- /*
- * If event was set from pd_prepare_sysjump, wake the
- * task waiting on us to complete.
- */
- if (sysjump_task_waiting != TASK_ID_INVALID)
- task_set_event(sysjump_task_waiting, TASK_EVENT_SYSJUMP_READY);
-}
-
-static inline bool is_pd_rev3(int port, enum tcpci_msg_type type)
-{
- return pd_get_rev(port, type) == PD_REV30;
-}
-
-/*
- * ############################################################################
- *
- * (Charge Through) Vconn Powered Device functions
- *
- * ############################################################################
- */
-bool is_vpd_ct_supported(int port)
-{
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
- union vpd_vdo vpd = disc->identity.product_t1.vpd;
-
- return vpd.ct_support;
-}
-
-uint8_t get_vpd_ct_gnd_impedance(int port)
-{
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
- union vpd_vdo vpd = disc->identity.product_t1.vpd;
-
- return vpd.gnd_impedance;
-}
-
-uint8_t get_vpd_ct_vbus_impedance(int port)
-{
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
- union vpd_vdo vpd = disc->identity.product_t1.vpd;
-
- return vpd.vbus_impedance;
-}
-
-uint8_t get_vpd_ct_current_support(int port)
-{
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
- union vpd_vdo vpd = disc->identity.product_t1.vpd;
-
- return vpd.ct_current_support;
-}
-
-uint8_t get_vpd_ct_max_vbus_voltage(int port)
-{
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
- union vpd_vdo vpd = disc->identity.product_t1.vpd;
-
- return vpd.max_vbus_voltage;
-}
-
-uint8_t get_vpd_ct_vdo_version(int port)
-{
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
- union vpd_vdo vpd = disc->identity.product_t1.vpd;
-
- return vpd.vdo_version;
-}
-
-uint8_t get_vpd_ct_firmware_verion(int port)
-{
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
- union vpd_vdo vpd = disc->identity.product_t1.vpd;
-
- return vpd.firmware_version;
-}
-
-uint8_t get_vpd_ct_hw_version(int port)
-{
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
- union vpd_vdo vpd = disc->identity.product_t1.vpd;
-
- return vpd.hw_version;
-}
-
-/*
- * ############################################################################
- *
- * Cable communication functions
- *
- * ############################################################################
- */
-enum idh_ptype get_usb_pd_cable_type(int port)
-{
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
-
- return disc->identity.idh.product_type;
-}
-
-bool is_usb2_cable_support(int port)
-{
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
-
- return disc->identity.idh.product_type == IDH_PTYPE_PCABLE ||
- pd_get_vdo_ver(port, TCPCI_MSG_SOP_PRIME) < VDM_VER20 ||
- disc->identity.product_t2.a2_rev30.usb_20_support ==
- USB2_SUPPORTED;
-}
-
-bool is_cable_speed_gen2_capable(int port)
-{
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
-
- switch (pd_get_rev(port, TCPCI_MSG_SOP_PRIME)) {
- case PD_REV20:
- return disc->identity.product_t1.p_rev20.ss ==
- USB_R20_SS_U31_GEN1_GEN2;
-
- case PD_REV30:
- return disc->identity.product_t1.p_rev30.ss ==
- USB_R30_SS_U32_U40_GEN2 ||
- disc->identity.product_t1.p_rev30.ss ==
- USB_R30_SS_U40_GEN3;
- default:
- return false;
- }
-}
-
-bool is_active_cable_element_retimer(int port)
-{
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
-
- /* Ref: USB PD Spec 2.0 Table 6-29 Active Cable VDO
- * Revision 2 Active cables do not have Active element support.
- */
- return is_pd_rev3(port, TCPCI_MSG_SOP_PRIME) &&
- disc->identity.idh.product_type == IDH_PTYPE_ACABLE &&
- disc->identity.product_t2.a2_rev30.active_elem ==
- ACTIVE_RETIMER;
-}
-
-/*
- * ############################################################################
- *
- * Thunderbolt-Compatible functions
- *
- * ############################################################################
- */
-
-uint32_t pd_get_tbt_mode_vdo(int port, enum tcpci_msg_type type)
-{
- uint32_t tbt_mode_vdo[PDO_MODES];
-
- return pd_get_mode_vdo_for_svid(port, type, USB_VID_INTEL,
- tbt_mode_vdo) ? tbt_mode_vdo[0] : 0;
-}
-
-/* TODO (b/148528713): Need to enable Thunderbolt-compatible mode on TCPMv2 */
-void set_tbt_compat_mode_ready(int port)
-{
- if (IS_ENABLED(CONFIG_USBC_SS_MUX) &&
- IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE)) {
- /* Connect the SBU and USB lines to the connector. */
- if (IS_ENABLED(CONFIG_USBC_PPC_SBU))
- ppc_set_sbu(port, 1);
-
- /* Set usb mux to Thunderbolt-compatible mode */
- usb_mux_set(port, USB_PD_MUX_TBT_COMPAT_ENABLED,
- USB_SWITCH_CONNECT,
- polarity_rm_dts(pd_get_polarity(port)));
- }
-}
-
-/*
- * Ref: USB Type-C Cable and Connector Specification
- * Figure F-1 TBT3 Discovery Flow
- */
-static bool is_tbt_cable_superspeed(int port)
-{
- const struct pd_discovery *disc;
-
- if (!IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) ||
- !IS_ENABLED(CONFIG_USB_PD_DECODE_SOP))
- return false;
-
- disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
-
- /* Product type is Active cable, hence don't check for speed */
- if (disc->identity.idh.product_type == IDH_PTYPE_ACABLE)
- return true;
-
- if (disc->identity.idh.product_type != IDH_PTYPE_PCABLE)
- return false;
-
- if (IS_ENABLED(CONFIG_USB_PD_REV30) &&
- is_pd_rev3(port, TCPCI_MSG_SOP_PRIME))
- return disc->identity.product_t1.p_rev30.ss ==
- USB_R30_SS_U32_U40_GEN1 ||
- disc->identity.product_t1.p_rev30.ss ==
- USB_R30_SS_U32_U40_GEN2 ||
- disc->identity.product_t1.p_rev30.ss ==
- USB_R30_SS_U40_GEN3;
-
- return disc->identity.product_t1.p_rev20.ss ==
- USB_R20_SS_U31_GEN1 ||
- disc->identity.product_t1.p_rev20.ss ==
- USB_R20_SS_U31_GEN1_GEN2;
-}
-
-static enum tbt_compat_cable_speed usb_rev30_to_tbt_speed(enum usb_rev30_ss ss)
-{
- switch (ss) {
- case USB_R30_SS_U32_U40_GEN1:
- return TBT_SS_U31_GEN1;
- case USB_R30_SS_U32_U40_GEN2:
- return TBT_SS_U32_GEN1_GEN2;
- case USB_R30_SS_U40_GEN3:
- return TBT_SS_TBT_GEN3;
- default:
- return TBT_SS_U32_GEN1_GEN2;
- }
-}
-
-enum tbt_compat_cable_speed get_tbt_cable_speed(int port)
-{
- union tbt_mode_resp_cable cable_mode_resp;
- enum tbt_compat_cable_speed max_tbt_speed;
- enum tbt_compat_cable_speed cable_tbt_speed;
-
- if (!is_tbt_cable_superspeed(port))
- return TBT_SS_RES_0;
-
- cable_mode_resp.raw_value =
- pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME);
- max_tbt_speed = board_get_max_tbt_speed(port);
-
- /*
- * Ref: TBT4 PD Discovery Flow Application Notes Revision 0.9, Figure 2
- * For passive cable, if cable doesn't support USB_VID_INTEL, enter
- * Thunderbolt alternate mode with speed from USB Highest Speed field of
- * the Passive Cable VDO
- * For active cable, if the cable doesn't support USB_VID_INTEL, do not
- * enter Thunderbolt alternate mode.
- */
- if (!cable_mode_resp.raw_value) {
- const struct pd_discovery *disc;
-
- if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE)
- return TBT_SS_RES_0;
-
- disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
- cable_tbt_speed =
- usb_rev30_to_tbt_speed(disc->identity.product_t1.p_rev30.ss);
- } else {
- cable_tbt_speed = cable_mode_resp.tbt_cable_speed;
- }
-
- return max_tbt_speed < cable_tbt_speed ?
- max_tbt_speed : cable_tbt_speed;
-}
-
-int enter_tbt_compat_mode(int port, enum tcpci_msg_type sop,
- uint32_t *payload)
-{
- union tbt_dev_mode_enter_cmd enter_dev_mode = { .raw_value = 0 };
- union tbt_mode_resp_device dev_mode_resp;
- union tbt_mode_resp_cable cable_mode_resp;
- enum tcpci_msg_type enter_mode_sop =
- sop == TCPCI_MSG_SOP_PRIME_PRIME ?
- TCPCI_MSG_SOP_PRIME : sop;
-
- /* Table F-12 TBT3 Cable Enter Mode Command */
- /*
- * The port doesn't query Discover SOP'' to the cable so, the port
- * doesn't have opos for SOP''. Hence, send Enter Mode SOP'' with same
- * opos and revision as SOP'.
- */
- payload[0] = pd_dfp_enter_mode(port, enter_mode_sop, USB_VID_INTEL, 0) |
- VDO_CMDT(CMDT_INIT) |
- VDO_SVDM_VERS(pd_get_vdo_ver(port, enter_mode_sop));
-
- /*
- * Enter safe mode before sending Enter mode SOP/SOP'/SOP''
- * Ref: Tiger Lake Platform PD Controller Interface Requirements for
- * Integrated USB C, section A.1.2 TBT as DFP.
- */
- usb_mux_set_safe_mode(port);
-
- /* For TBT3 Cable Enter Mode Command, number of Objects is 1 */
- if ((sop == TCPCI_MSG_SOP_PRIME) ||
- (sop == TCPCI_MSG_SOP_PRIME_PRIME))
- return 1;
-
- dev_mode_resp.raw_value = pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP);
- cable_mode_resp.raw_value =
- pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME);
-
- /* Table F-13 TBT3 Device Enter Mode Command */
- enter_dev_mode.vendor_spec_b1 = dev_mode_resp.vendor_spec_b1;
- enter_dev_mode.vendor_spec_b0 = dev_mode_resp.vendor_spec_b0;
- enter_dev_mode.intel_spec_b0 = dev_mode_resp.intel_spec_b0;
-
- if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE ||
- cable_mode_resp.tbt_active_passive == TBT_CABLE_ACTIVE)
- enter_dev_mode.cable = TBT_ENTER_ACTIVE_CABLE;
-
- enter_dev_mode.lsrx_comm = cable_mode_resp.lsrx_comm;
- enter_dev_mode.retimer_type = cable_mode_resp.retimer_type;
- enter_dev_mode.tbt_cable = cable_mode_resp.tbt_cable;
- enter_dev_mode.tbt_rounded = cable_mode_resp.tbt_rounded;
- enter_dev_mode.tbt_cable_speed = get_tbt_cable_speed(port);
- enter_dev_mode.tbt_alt_mode = TBT_ALTERNATE_MODE;
-
- payload[1] = enter_dev_mode.raw_value;
-
- /* For TBT3 Device Enter Mode Command, number of Objects are 2 */
- return 2;
-}
-
-enum tbt_compat_rounded_support get_tbt_rounded_support(int port)
-{
- union tbt_mode_resp_cable cable_mode_resp = {
- .raw_value = pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME) };
-
- /* tbt_rounded_support is zero when uninitialized */
- return cable_mode_resp.tbt_rounded;
-}
-
-__overridable enum tbt_compat_cable_speed board_get_max_tbt_speed(int port)
-{
- return TBT_SS_TBT_GEN3;
-}
-/*
- * ############################################################################
- *
- * USB4 functions
- *
- * ############################################################################
- */
-
-/*
- * For Cable rev 3.0: USB4 cable speed is set according to speed supported by
- * the port and the response received from the cable, whichever is least.
- *
- * For Cable rev 2.0: If get_tbt_cable_speed() is less than
- * TBT_SS_U31_GEN1, return USB_R30_SS_U2_ONLY speed since the board
- * doesn't support superspeed else the USB4 cable speed is set according to
- * the cable response.
- */
-enum usb_rev30_ss get_usb4_cable_speed(int port)
-{
- enum tbt_compat_cable_speed tbt_speed = get_tbt_cable_speed(port);
- enum usb_rev30_ss max_usb4_speed;
-
-
- if (tbt_speed < TBT_SS_U31_GEN1)
- return USB_R30_SS_U2_ONLY;
-
- /*
- * Converting Thunderbolt-Compatible board speed to equivalent USB4
- * speed.
- */
- max_usb4_speed = tbt_speed == TBT_SS_TBT_GEN3 ?
- USB_R30_SS_U40_GEN3 : USB_R30_SS_U32_U40_GEN2;
-
- if ((get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) &&
- is_pd_rev3(port, TCPCI_MSG_SOP_PRIME)) {
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
- union active_cable_vdo1_rev30 a_rev30 =
- disc->identity.product_t1.a_rev30;
-
- if (a_rev30.vdo_ver >= VDO_VERSION_1_3) {
- return max_usb4_speed < a_rev30.ss ?
- max_usb4_speed : a_rev30.ss;
- }
- }
-
- return max_usb4_speed;
-}
-
-uint32_t get_enter_usb_msg_payload(int port)
-{
- /*
- * Ref: USB Power Delivery Specification Revision 3.0, Version 2.0
- * Table 6-47 Enter_USB Data Object
- */
- union enter_usb_data_obj eudo;
- const struct pd_discovery *disc;
- union tbt_mode_resp_cable cable_mode_resp;
-
- if (!IS_ENABLED(CONFIG_USB_PD_USB4))
- return 0;
-
- disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
- eudo.mode = USB_PD_40;
- eudo.usb4_drd_cap = IS_ENABLED(CONFIG_USB_PD_USB4_DRD);
- eudo.usb3_drd_cap = IS_ENABLED(CONFIG_USB_PD_USB32_DRD);
- eudo.cable_speed = get_usb4_cable_speed(port);
-
- if (disc->identity.idh.product_type == IDH_PTYPE_ACABLE) {
- if (is_pd_rev3(port, TCPCI_MSG_SOP_PRIME)) {
- enum retimer_active_element active_element =
- disc->identity.product_t2.a2_rev30.active_elem;
- eudo.cable_type = active_element == ACTIVE_RETIMER ?
- CABLE_TYPE_ACTIVE_RETIMER :
- CABLE_TYPE_ACTIVE_REDRIVER;
- } else {
- cable_mode_resp.raw_value =
- pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME);
-
- eudo.cable_type =
- cable_mode_resp.retimer_type == USB_RETIMER ?
- CABLE_TYPE_ACTIVE_RETIMER :
- CABLE_TYPE_ACTIVE_REDRIVER;
- }
- } else {
- cable_mode_resp.raw_value =
- pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME);
-
- eudo.cable_type =
- cable_mode_resp.tbt_active_passive == TBT_CABLE_ACTIVE ?
- CABLE_TYPE_ACTIVE_REDRIVER : CABLE_TYPE_PASSIVE;
- }
-
- switch (disc->identity.product_t1.p_rev20.vbus_cur) {
- case USB_VBUS_CUR_3A:
- eudo.cable_current = USB4_CABLE_CURRENT_3A;
- break;
- case USB_VBUS_CUR_5A:
- eudo.cable_current = USB4_CABLE_CURRENT_5A;
- break;
- default:
- eudo.cable_current = USB4_CABLE_CURRENT_INVALID;
- break;
- }
- eudo.pcie_supported = IS_ENABLED(CONFIG_USB_PD_PCIE_TUNNELING);
- eudo.dp_supported = IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP);
- eudo.tbt_supported = IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE);
- eudo.host_present = 1;
-
- return eudo.raw_value;
-}
-
-__overridable bool board_is_tbt_usb4_port(int port)
-{
- return true;
-}
-
-__overridable void svdm_safe_dp_mode(int port)
-{
- /* make DP interface safe until configure */
- dp_flags[port] = 0;
- dp_status[port] = 0;
-
- usb_mux_set_safe_mode(port);
-}
-
-__overridable int svdm_enter_dp_mode(int port, uint32_t mode_caps)
-{
- /*
- * Don't enter the mode if the SoC is off.
- *
- * There's no need to enter the mode while the SoC is off; we'll
- * actually enter the mode on the chipset resume hook. Entering DP Alt
- * Mode twice will confuse some monitors and require and unplug/replug
- * to get them to work again. The DP Alt Mode on USB-C spec says that
- * if we don't need to maintain HPD connectivity info in a low power
- * mode, then we shall exit DP Alt Mode. (This is why we don't enter
- * when the SoC is off as opposed to suspend where adding a display
- * could cause a wake up.) When in S5->S3 transition state, we
- * should treat it as a SoC off state.
- */
-#ifdef HAS_TASK_CHIPSET
- if (!chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON))
- return -1;
-#endif
-
- /*
- * TCPMv2: Enable logging of CCD line state CCD_MODE_ODL.
- * DisplayPort Alternate mode requires that the SBU lines are used for
- * AUX communication.
- * However, in Chromebooks SBU signals are repurposed as USB2 signals
- * for CCD. This functionality is accomplished by override fets whose
- * state is controlled by CCD_MODE_ODL.
- *
- * This condition helps in debugging unexpected AUX timeout issues by
- * indicating the state of the CCD override fets.
- */
-#ifdef GPIO_CCD_MODE_ODL
- if (!gpio_get_level(GPIO_CCD_MODE_ODL))
- CPRINTS("WARNING: Tried to EnterMode DP with [CCD on AUX/SBU]");
-#endif
-
- /* Only enter mode if device is DFP_D capable */
- if (mode_caps & MODE_DP_SNK) {
- svdm_safe_dp_mode(port);
-
- if (IS_ENABLED(CONFIG_MKBP_EVENT) &&
- chipset_in_state(CHIPSET_STATE_ANY_SUSPEND))
- /*
- * Wake the system up since we're entering DP AltMode.
- */
- pd_notify_dp_alt_mode_entry(port);
-
- return 0;
- }
-
- return -1;
-}
-
-__overridable int svdm_dp_status(int port, uint32_t *payload)
-{
- int opos = pd_alt_mode(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT);
-
- payload[0] = VDO(USB_SID_DISPLAYPORT, 1,
- CMD_DP_STATUS | VDO_OPOS(opos));
- payload[1] = VDO_DP_STATUS(0, /* HPD IRQ ... not applicable */
- 0, /* HPD level ... not applicable */
- 0, /* exit DP? ... no */
- 0, /* usb mode? ... no */
- 0, /* multi-function ... no */
- (!!(dp_flags[port] & DP_FLAGS_DP_ON)),
- 0, /* power low? ... no */
- (!!DP_FLAGS_DP_ON));
- return 2;
-};
-
-__overridable uint8_t get_dp_pin_mode(int port)
-{
- return pd_dfp_dp_get_pin_mode(port, dp_status[port]);
-}
-
-static mux_state_t svdm_dp_get_mux_mode(int port)
-{
- int pin_mode = get_dp_pin_mode(port);
- /* Default dp_port_mf_allow is true */
- int mf_pref;
-
- if (IS_ENABLED(CONFIG_CMD_MFALLOW))
- mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]) &&
- dp_port_mf_allow[port];
- else
- mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]);
-
- /*
- * Multi-function operation is only allowed if that pin config is
- * supported.
- */
- if ((pin_mode & MODE_DP_PIN_MF_MASK) && mf_pref)
- return USB_PD_MUX_DOCK;
- else
- return USB_PD_MUX_DP_ENABLED;
-}
-
-__overridable int svdm_dp_config(int port, uint32_t *payload)
-{
- int opos = pd_alt_mode(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT);
- uint8_t pin_mode = get_dp_pin_mode(port);
- mux_state_t mux_mode = svdm_dp_get_mux_mode(port);
- /* Default dp_port_mf_allow is true */
- int mf_pref;
-
- if (IS_ENABLED(CONFIG_CMD_MFALLOW))
- mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]) &&
- dp_port_mf_allow[port];
- else
- mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]);
-
- if (!pin_mode)
- return 0;
-
- CPRINTS("pin_mode: %x, mf: %d, mux: %d", pin_mode, mf_pref, mux_mode);
-
- /*
- * Place the USB Type-C pins that are to be re-configured to DisplayPort
- * Configuration into the Safe state. For USB_PD_MUX_DOCK, the
- * superspeed signals can remain connected. For USB_PD_MUX_DP_ENABLED,
- * disconnect the superspeed signals here, before the pins are
- * re-configured to DisplayPort (in svdm_dp_post_config, when we receive
- * the config ack).
- */
- if (mux_mode == USB_PD_MUX_DP_ENABLED)
- usb_mux_set_safe_mode(port);
-
- payload[0] = VDO(USB_SID_DISPLAYPORT, 1,
- CMD_DP_CONFIG | VDO_OPOS(opos));
- payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */
- 1, /* DPv1.3 signaling */
- 2); /* UFP connected */
- return 2;
-};
-
-#if defined(CONFIG_USB_PD_DP_HPD_GPIO) && \
- !defined(CONFIG_USB_PD_DP_HPD_GPIO_CUSTOM)
-void svdm_set_hpd_gpio(int port, int en)
-{
- gpio_set_level(PORT_TO_HPD(port), en);
-}
-
-int svdm_get_hpd_gpio(int port)
-{
- return gpio_get_level(PORT_TO_HPD(port));
-}
-#endif
-
-__overridable void svdm_dp_post_config(int port)
-{
- mux_state_t mux_mode = svdm_dp_get_mux_mode(port);
- /* Connect the SBU and USB lines to the connector. */
- if (IS_ENABLED(CONFIG_USBC_PPC_SBU))
- ppc_set_sbu(port, 1);
- usb_mux_set(port, mux_mode, USB_SWITCH_CONNECT,
- polarity_rm_dts(pd_get_polarity(port)));
-
- dp_flags[port] |= DP_FLAGS_DP_ON;
- if (!(dp_flags[port] & DP_FLAGS_HPD_HI_PENDING))
- return;
-
-#ifdef CONFIG_USB_PD_DP_HPD_GPIO
- svdm_set_hpd_gpio(port, 1);
-
- /* set the minimum time delay (2ms) for the next HPD IRQ */
- svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL;
-#endif /* CONFIG_USB_PD_DP_HPD_GPIO */
-
- usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL |
- USB_PD_MUX_HPD_IRQ_DEASSERTED);
-
-#ifdef USB_PD_PORT_TCPC_MST
- if (port == USB_PD_PORT_TCPC_MST)
- baseboard_mst_enable_control(port, 1);
-#endif
-}
-
-__overridable int svdm_dp_attention(int port, uint32_t *payload)
-{
- int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]);
- int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]);
-#ifdef CONFIG_USB_PD_DP_HPD_GPIO
- int cur_lvl = svdm_get_hpd_gpio(port);
-#endif /* CONFIG_USB_PD_DP_HPD_GPIO */
- mux_state_t mux_state;
-
- dp_status[port] = payload[1];
-
- if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) &&
- (irq || lvl))
- /*
- * Wake up the AP. IRQ or level high indicates a DP sink is now
- * present.
- */
- if (IS_ENABLED(CONFIG_MKBP_EVENT))
- pd_notify_dp_alt_mode_entry(port);
-
- /* Its initial DP status message prior to config */
- if (!(dp_flags[port] & DP_FLAGS_DP_ON)) {
- if (lvl)
- dp_flags[port] |= DP_FLAGS_HPD_HI_PENDING;
- return 1;
- }
-
-#ifdef CONFIG_USB_PD_DP_HPD_GPIO
- if (irq && !lvl) {
- /*
- * IRQ can only be generated when the level is high, because
- * the IRQ is signaled by a short low pulse from the high level.
- */
- CPRINTF("ERR:HPD:IRQ&LOW\n");
- return 0; /* nak */
- }
-
- if (irq && cur_lvl) {
- uint64_t now = get_time().val;
- /* wait for the minimum spacing between IRQ_HPD if needed */
- if (now < svdm_hpd_deadline[port])
- usleep(svdm_hpd_deadline[port] - now);
-
- /* generate IRQ_HPD pulse */
- svdm_set_hpd_gpio(port, 0);
- usleep(HPD_DSTREAM_DEBOUNCE_IRQ);
- svdm_set_hpd_gpio(port, 1);
- } else {
- svdm_set_hpd_gpio(port, lvl);
- }
-
- /* set the minimum time delay (2ms) for the next HPD IRQ */
- svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL;
-#endif /* CONFIG_USB_PD_DP_HPD_GPIO */
-
- mux_state = (lvl ? USB_PD_MUX_HPD_LVL : USB_PD_MUX_HPD_LVL_DEASSERTED) |
- (irq ? USB_PD_MUX_HPD_IRQ : USB_PD_MUX_HPD_IRQ_DEASSERTED);
- usb_mux_hpd_update(port, mux_state);
-
-#ifdef USB_PD_PORT_TCPC_MST
- if (port == USB_PD_PORT_TCPC_MST)
- baseboard_mst_enable_control(port, lvl);
-#endif
-
- /* ack */
- return 1;
-}
-
-__overridable void svdm_exit_dp_mode(int port)
-{
- dp_flags[port] = 0;
- dp_status[port] = 0;
-#ifdef CONFIG_USB_PD_DP_HPD_GPIO
- svdm_set_hpd_gpio(port, 0);
-#endif /* CONFIG_USB_PD_DP_HPD_GPIO */
- usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED |
- USB_PD_MUX_HPD_IRQ_DEASSERTED);
-#ifdef USB_PD_PORT_TCPC_MST
- if (port == USB_PD_PORT_TCPC_MST)
- baseboard_mst_enable_control(port, 0);
-#endif
-}
-
-__overridable int svdm_enter_gfu_mode(int port, uint32_t mode_caps)
-{
- /* Always enter GFU mode */
- return 0;
-}
-
-__overridable void svdm_exit_gfu_mode(int port)
-{
-}
-
-__overridable int svdm_gfu_status(int port, uint32_t *payload)
-{
- /*
- * This is called after enter mode is successful, send unstructured
- * VDM to read info.
- */
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_READ_INFO, NULL, 0);
- return 0;
-}
-
-__overridable int svdm_gfu_config(int port, uint32_t *payload)
-{
- return 0;
-}
-
-__overridable int svdm_gfu_attention(int port, uint32_t *payload)
-{
- return 0;
-}
-
-#ifdef CONFIG_USB_PD_TBT_COMPAT_MODE
-__overridable int svdm_tbt_compat_enter_mode(int port, uint32_t mode_caps)
-{
- return 0;
-}
-
-__overridable void svdm_tbt_compat_exit_mode(int port)
-{
-}
-
-__overridable int svdm_tbt_compat_status(int port, uint32_t *payload)
-{
- return 0;
-}
-
-__overridable int svdm_tbt_compat_config(int port, uint32_t *payload)
-{
- return 0;
-}
-
-__overridable int svdm_tbt_compat_attention(int port, uint32_t *payload)
-{
- return 0;
-}
-#endif /* CONFIG_USB_PD_TBT_COMPAT_MODE */
-
-/*
- * TODO: b:169262276: For TCPMv2, move alternate mode specific entry, exit and
- * configuration to Device Policy Manager.
- */
-const struct svdm_amode_fx supported_modes[] = {
- {
- .svid = USB_SID_DISPLAYPORT,
- .enter = &svdm_enter_dp_mode,
- .status = &svdm_dp_status,
- .config = &svdm_dp_config,
- .post_config = &svdm_dp_post_config,
- .attention = &svdm_dp_attention,
- .exit = &svdm_exit_dp_mode,
- },
-
- {
- .svid = USB_VID_GOOGLE,
- .enter = &svdm_enter_gfu_mode,
- .status = &svdm_gfu_status,
- .config = &svdm_gfu_config,
- .attention = &svdm_gfu_attention,
- .exit = &svdm_exit_gfu_mode,
- },
-#ifdef CONFIG_USB_PD_TBT_COMPAT_MODE
- {
- .svid = USB_VID_INTEL,
- .enter = &svdm_tbt_compat_enter_mode,
- .status = &svdm_tbt_compat_status,
- .config = &svdm_tbt_compat_config,
- .attention = &svdm_tbt_compat_attention,
- .exit = &svdm_tbt_compat_exit_mode,
- },
-#endif /* CONFIG_USB_PD_TBT_COMPAT_MODE */
-};
-const int supported_modes_cnt = ARRAY_SIZE(supported_modes);
-
-#ifdef CONFIG_CMD_MFALLOW
-static int command_mfallow(int argc, char **argv)
-{
- char *e;
- int port;
-
- if (argc < 3)
- return EC_ERROR_PARAM_COUNT;
-
- port = strtoi(argv[1], &e, 10);
- if (*e || port >= board_get_usb_pd_port_count())
- return EC_ERROR_PARAM2;
-
- if (!strcasecmp(argv[2], "true"))
- dp_port_mf_allow[port] = true;
- else if (!strcasecmp(argv[2], "false"))
- dp_port_mf_allow[port] = false;
- else
- return EC_ERROR_PARAM1;
-
- ccprintf("Port: %d multi function allowed is %s ", port, argv[2]);
- return EC_SUCCESS;
-}
-
-DECLARE_CONSOLE_COMMAND(mfallow, command_mfallow, "port [true | false]",
- "Controls Multifunction choice during DP Altmode.");
-#endif
diff --git a/common/usb_pd_alt_mode_ufp.c b/common/usb_pd_alt_mode_ufp.c
deleted file mode 100644
index 3db60166d2..0000000000
--- a/common/usb_pd_alt_mode_ufp.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Copyright 2021 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.
- *
- * Alternate Mode Upstream Facing Port (UFP) USB-PD module.
- */
-#include "usb_pd.h"
-#include "usb_tbt_alt_mode.h"
-
-static uint32_t ufp_enter_mode[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Save port partner's enter mode message */
-void pd_ufp_set_enter_mode(int port, uint32_t *payload)
-{
- ufp_enter_mode[port] = payload[1];
-}
-
-/* Return port partner's enter mode message */
-uint32_t pd_ufp_get_enter_mode(int port)
-{
- return ufp_enter_mode[port];
-}
diff --git a/common/usb_pd_console_cmd.c b/common/usb_pd_console_cmd.c
deleted file mode 100644
index 3ad1944494..0000000000
--- a/common/usb_pd_console_cmd.c
+++ /dev/null
@@ -1,224 +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.
- *
- * Console commands for USB-PD module.
- */
-
-#include "console.h"
-#include "usb_pd.h"
-#include "util.h"
-#include "usb_pd_tcpm.h"
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-#ifdef CONFIG_CMD_USB_PD_PE
-static void dump_pe(int port)
-{
- int i, j, idh_ptype;
- struct svdm_amode_data *modep;
- uint32_t mode_caps;
- const union disc_ident_ack *resp;
- enum tcpci_msg_type type;
- /* TODO(b/152417597): Output SOP' discovery results */
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP);
-
- static const char * const idh_ptype_names[] = {
- "UNDEF", "Hub", "Periph", "PCable", "ACable", "AMA",
- "RSV6", "RSV7"};
- static const char * const tx_names[] = {"SOP", "SOP'", "SOP''"};
-
- for (type = TCPCI_MSG_SOP; type < DISCOVERY_TYPE_COUNT; type++) {
- resp = pd_get_identity_response(port, type);
- if (pd_get_identity_discovery(port, type) != PD_DISC_COMPLETE) {
- ccprintf("No %s identity discovered yet.\n",
- tx_names[type]);
- continue;
- }
-
- idh_ptype = resp->idh.product_type;
- ccprintf("IDENT %s:\n", tx_names[type]);
- ccprintf("\t[ID Header] %08x :: %s, VID:%04x\n",
- resp->raw_value[0],
- idh_ptype_names[idh_ptype],
- resp->idh.usb_vendor_id);
-
- ccprintf("\t[Cert Stat] %08x\n", resp->cert.xid);
- for (i = 2; i < ARRAY_SIZE(resp->raw_value); i++) {
- ccprintf("\t");
- if (resp->raw_value[i])
- ccprintf("[%d] %08x ", i, resp->raw_value[i]);
- }
- ccprintf("\n");
- }
-
- if (pd_get_svid_count(port, TCPCI_MSG_SOP) < 1) {
- ccprintf("No SVIDS discovered yet.\n");
- return;
- }
-
- /* TODO(b/152418267): Display discovered SVIDs and modes for SOP' */
- for (i = 0; i < pd_get_svid_count(port, TCPCI_MSG_SOP); i++) {
- ccprintf("SVID[%d]: %04x MODES:", i, disc->svids[i].svid);
- for (j = 0; j < disc->svids[j].mode_cnt; j++)
- ccprintf(" [%d] %08x", j + 1,
- disc->svids[i].mode_vdo[j]);
- ccprintf("\n");
-
- modep = pd_get_amode_data(port, TCPCI_MSG_SOP,
- disc->svids[i].svid);
- if (modep) {
- mode_caps = modep->data->mode_vdo[modep->opos - 1];
- ccprintf("MODE[%d]: svid:%04x caps:%08x\n", modep->opos,
- modep->fx->svid, mode_caps);
- }
- }
-}
-
-static int command_pe(int argc, char **argv)
-{
- int port;
- char *e;
-
- if (argc < 3)
- return EC_ERROR_PARAM_COUNT;
-
- /* command: pe <port> <subcmd> <args> */
- port = strtoi(argv[1], &e, 10);
- if (*e || port >= board_get_usb_pd_port_count())
- return EC_ERROR_PARAM2;
- if (!strncasecmp(argv[2], "dump", 4))
- dump_pe(port);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(pe, command_pe,
- "<port> dump",
- "USB PE");
-#endif /* CONFIG_CMD_USB_PD_PE */
-
-#ifdef CONFIG_CMD_USB_PD_CABLE
-static const char * const cable_type[] = {
- [IDH_PTYPE_PCABLE] = "Passive",
- [IDH_PTYPE_ACABLE] = "Active",
-};
-
-static const char * const cable_curr[] = {
- [USB_VBUS_CUR_3A] = "3A",
- [USB_VBUS_CUR_5A] = "5A",
-};
-
-static int command_cable(int argc, char **argv)
-{
- int port;
- char *e;
- const struct pd_discovery *disc;
- enum idh_ptype ptype;
- int cable_rev;
- union tbt_mode_resp_cable cable_mode_resp;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- port = strtoi(argv[1], &e, 0);
- if (*e || port >= board_get_usb_pd_port_count())
- return EC_ERROR_PARAM2;
-
- ptype = get_usb_pd_cable_type(port);
-
- ccprintf("Cable Type: ");
- if (ptype != IDH_PTYPE_PCABLE &&
- ptype != IDH_PTYPE_ACABLE) {
- ccprintf("Not Emark Cable\n");
- return EC_SUCCESS;
- }
- ccprintf("%s\n", cable_type[ptype]);
-
- cable_rev = pd_get_rev(port, TCPCI_MSG_SOP_PRIME);
- disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
- cable_mode_resp.raw_value =
- pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME);
-
-
- /* Cable revision */
- ccprintf("Cable Rev: %d.0\n", cable_rev + 1);
-
- /*
- * For rev 2.0, rev 3.0 active and passive cables have same bits for
- * connector type (Bit 19:18) and current handling capability bit 6:5
- */
- ccprintf("Connector Type: %d\n",
- disc->identity.product_t1.p_rev20.connector);
-
- if (disc->identity.product_t1.p_rev20.vbus_cur) {
- ccprintf("Cable Current: %s\n",
- disc->identity.product_t1.p_rev20.vbus_cur >
- ARRAY_SIZE(cable_curr) ? "Invalid" :
- cable_curr[disc->identity.product_t1.p_rev20.vbus_cur]);
- } else
- ccprintf("Cable Current: Invalid\n");
-
- /*
- * For Rev 3.0 passive cables and Rev 2.0 active and passive cables,
- * USB Superspeed Signaling support have same bits 2:0
- */
- if (ptype == IDH_PTYPE_PCABLE)
- ccprintf("USB Superspeed Signaling support: %d\n",
- disc->identity.product_t1.p_rev20.ss);
-
- /*
- * For Rev 3.0 active cables and Rev 2.0 active and passive cables,
- * SOP" controller preset have same bit 3
- */
- if (ptype == IDH_PTYPE_ACABLE)
- ccprintf("SOP'' Controller: %s present\n",
- disc->identity.product_t1.a_rev20.sop_p_p ? "" : "Not");
-
- if (cable_rev == PD_REV30) {
- /*
- * For Rev 3.0 active and passive cables, Max Vbus vtg have
- * same bits 10:9.
- */
- ccprintf("Max vbus voltage: %d\n",
- 20 + 10 * disc->identity.product_t1.p_rev30.vbus_max);
-
- /* For Rev 3.0 Active cables */
- if (ptype == IDH_PTYPE_ACABLE) {
- ccprintf("SS signaling: USB_SS_GEN%u\n",
- disc->identity.product_t2.a2_rev30.usb_gen ?
- 2 : 1);
- ccprintf("Number of SS lanes supported: %u\n",
- disc->identity.product_t2.a2_rev30.usb_lanes);
- }
- }
-
- if (!cable_mode_resp.raw_value)
- return EC_SUCCESS;
-
- ccprintf("Rounded support: %s\n",
- cable_mode_resp.tbt_rounded ==
- TBT_GEN3_GEN4_ROUNDED_NON_ROUNDED ? "Yes" : "No");
-
- ccprintf("Optical cable: %s\n",
- cable_mode_resp.tbt_cable == TBT_CABLE_OPTICAL ? "Yes" : "No");
-
- ccprintf("Retimer support: %s\n",
- cable_mode_resp.retimer_type == USB_RETIMER ?
- "Yes" : "No");
-
- ccprintf("Link training: %s-directional\n",
- cable_mode_resp.lsrx_comm == BIDIR_LSRX_COMM ? "Bi" : "Uni");
-
- ccprintf("Thunderbolt cable type: %s\n",
- cable_mode_resp.tbt_active_passive == TBT_CABLE_ACTIVE ?
- "Active" : "Passive");
-
- return EC_SUCCESS;
-}
-
-DECLARE_CONSOLE_COMMAND(pdcable, command_cable,
- "<port>",
- "Cable Characteristics");
-#endif /* CONFIG_CMD_USB_PD_CABLE */
-
-#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
diff --git a/common/usb_pd_dual_role.c b/common/usb_pd_dual_role.c
deleted file mode 100644
index 52042c5439..0000000000
--- a/common/usb_pd_dual_role.c
+++ /dev/null
@@ -1,473 +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.
- *
- * Dual Role (Source & Sink) USB-PD module.
- */
-
-#include "charge_manager.h"
-#include "charge_state.h"
-#include "dps.h"
-#include "system.h"
-#include "usb_common.h"
-#include "usb_pd.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-
-/* The macro is used to prevent a DBZ exception while decoding PDOs. */
-#define PROCESS_ZERO_DIVISOR(x) ((x) == 0 ? 1 : (x))
-
-#if defined(PD_MAX_VOLTAGE_MV) && defined(PD_OPERATING_POWER_MW)
-/*
- * As a sink, this is the max voltage (in millivolts) we can request
- * before getting source caps
- */
-static unsigned int max_request_mv = PD_MAX_VOLTAGE_MV;
-
-/* TODO(b:169532537): deprecate CONFIG_USB_PD_PREFER_MV */
-STATIC_IF_NOT(CONFIG_USB_PD_PREFER_MV)
-struct pd_pref_config_t __maybe_unused pd_pref_config;
-
-void pd_set_max_voltage(unsigned int mv)
-{
- max_request_mv = mv;
-}
-
-unsigned int pd_get_max_voltage(void)
-{
- return max_request_mv;
-}
-
-/*
- * Zinger implements a board specific usb policy that does not define
- * PD_MAX_VOLTAGE_MV and PD_OPERATING_POWER_MW. And in turn, does not
- * use the following functions.
- */
-int pd_find_pdo_index(uint32_t src_cap_cnt, const uint32_t * const src_caps,
- int max_mv, uint32_t *selected_pdo)
-{
- int i, uw, mv;
- int ret = 0;
- int cur_uw = 0;
- int has_preferred_pdo;
- int prefer_cur;
- int desired_uw = 0;
- const int prefer_mv = pd_pref_config.mv;
- const int type = pd_pref_config.type;
-
- int __attribute__((unused)) cur_mv = 0;
-
- if (IS_ENABLED(CONFIG_USB_PD_PREFER_MV))
- desired_uw = charge_get_plt_plus_bat_desired_mw() * 1000;
-
- /* max voltage is always limited by this boards max request */
- max_mv = MIN(max_mv, PD_MAX_VOLTAGE_MV);
-
- /* Get max power that is under our max voltage input */
- for (i = 0; i < src_cap_cnt; i++) {
- if (IS_ENABLED(CONFIG_USB_PD_ONLY_FIXED_PDOS) &&
- (src_caps[i] & PDO_TYPE_MASK) != PDO_TYPE_FIXED)
- continue;
- /* its an unsupported Augmented PDO (PD3.0) */
- if ((src_caps[i] & PDO_TYPE_MASK) == PDO_TYPE_AUGMENTED)
- continue;
-
- mv = ((src_caps[i] >> 10) & 0x3FF) * 50;
- /* Skip invalid voltage */
- if (!mv)
- continue;
- /* Skip any voltage not supported by this board */
- if (!pd_is_valid_input_voltage(mv))
- continue;
-
- if ((src_caps[i] & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) {
- uw = 250000 * (src_caps[i] & 0x3FF);
- } else {
- int ma = (src_caps[i] & 0x3FF) * 10;
-
- ma = MIN(ma, PD_MAX_CURRENT_MA);
- uw = ma * mv;
- }
-
- if (mv > max_mv)
- continue;
- uw = MIN(uw, PD_MAX_POWER_MW * 1000);
- prefer_cur = 0;
-
- /* Apply special rules in favor of voltage */
- if (IS_ENABLED(PD_PREFER_LOW_VOLTAGE)) {
- if (uw == cur_uw && mv < cur_mv)
- prefer_cur = 1;
- } else if (IS_ENABLED(PD_PREFER_HIGH_VOLTAGE)) {
- if (uw == cur_uw && mv > cur_mv)
- prefer_cur = 1;
- } else if (IS_ENABLED(CONFIG_USB_PD_PREFER_MV)) {
- /* Pick if the PDO provides more than desired. */
- if (uw >= desired_uw) {
- /* pick if cur_uw is less than desired watt */
- if (cur_uw < desired_uw)
- prefer_cur = 1;
- else if (type == PD_PREFER_BUCK) {
- /*
- * pick the smallest mV above prefer_mv
- */
- if (mv >= prefer_mv && mv < cur_mv)
- prefer_cur = 1;
- /*
- * pick if cur_mv is less than
- * prefer_mv, and we have higher mV
- */
- else if (cur_mv < prefer_mv &&
- mv > cur_mv)
- prefer_cur = 1;
- } else if (type == PD_PREFER_BOOST) {
- /*
- * pick the largest mV below prefer_mv
- */
- if (mv <= prefer_mv && mv > cur_mv)
- prefer_cur = 1;
- /*
- * pick if cur_mv is larger than
- * prefer_mv, and we have lower mV
- */
- else if (cur_mv > prefer_mv &&
- mv < cur_mv)
- prefer_cur = 1;
- }
- /*
- * pick the largest power if we don't see one staisfy
- * desired power
- */
- } else if (cur_uw == 0 || uw > cur_uw) {
- prefer_cur = 1;
- }
- }
-
- /* Prefer higher power, except for tiebreaker */
- has_preferred_pdo =
- prefer_cur ||
- (!IS_ENABLED(CONFIG_USB_PD_PREFER_MV) && uw > cur_uw);
-
- if (has_preferred_pdo) {
- ret = i;
- cur_uw = uw;
- cur_mv = mv;
- }
- }
-
- if (selected_pdo)
- *selected_pdo = src_caps[ret];
-
- return ret;
-}
-
-void pd_extract_pdo_power(uint32_t pdo, uint32_t *ma, uint32_t *max_mv,
- uint32_t *min_mv)
-{
- int max_ma, mw;
-
- if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_FIXED) {
- *max_mv = PDO_FIXED_VOLTAGE(pdo);
- *min_mv = *max_mv;
- } else if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_AUGMENTED) {
- *max_mv = PDO_AUG_MAX_VOLTAGE(pdo);
- *min_mv = PDO_AUG_MIN_VOLTAGE(pdo);
- } else if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_VARIABLE) {
- *max_mv = PDO_VAR_MAX_VOLTAGE(pdo);
- *min_mv = PDO_VAR_MIN_VOLTAGE(pdo);
- } else {
- *max_mv = PDO_BATT_MAX_VOLTAGE(pdo);
- *min_mv = PDO_BATT_MIN_VOLTAGE(pdo);
- }
-
- if (*max_mv == 0) {
- *ma = 0;
- *min_mv = 0;
- return;
- }
-
- if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_FIXED) {
- max_ma = PDO_FIXED_CURRENT(pdo);
- } else if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_AUGMENTED) {
- max_ma = PDO_AUG_MAX_CURRENT(pdo);
- } else if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_VARIABLE) {
- max_ma = PDO_VAR_MAX_CURRENT(pdo);
- } else {
- mw = PDO_BATT_MAX_POWER(pdo);
- max_ma = 1000 * mw / PROCESS_ZERO_DIVISOR(*min_mv);
- }
- max_ma = MIN(max_ma,
- PD_MAX_POWER_MW * 1000 / PROCESS_ZERO_DIVISOR(*min_mv));
- *ma = MIN(max_ma, PD_MAX_CURRENT_MA);
-}
-
-void pd_build_request(int32_t vpd_vdo, uint32_t *rdo, uint32_t *ma,
- uint32_t *mv, int port)
-{
- uint32_t pdo;
- int pdo_index, flags = 0;
- int uw;
- int max_or_min_ma;
- int max_or_min_mw;
- int max_vbus;
- int vpd_vbus_dcr;
- int vpd_gnd_dcr;
- uint32_t src_cap_cnt = pd_get_src_cap_cnt(port);
- const uint32_t * const src_caps = pd_get_src_caps(port);
- int charging_allowed;
- int max_request_allowed;
- uint32_t max_request_mv = pd_get_max_voltage();
- uint32_t unused;
-
- /*
- * If this port is the current charge port, or if there isn't an active
- * charge port, set this value to true. If CHARGE_PORT_NONE isn't
- * considered, then there can be a race condition in PD negotiation and
- * the charge manager which forces an incorrect request for
- * vSafe5V. This can then lead to a brownout condition when the input
- * current limit gets incorrectly set to 0.5A.
- */
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) {
- int chg_port = charge_manager_get_selected_charge_port();
-
- charging_allowed =
- (chg_port == port || chg_port == CHARGE_PORT_NONE);
- } else {
- charging_allowed = 1;
- }
-
- if (IS_ENABLED(CONFIG_USB_PD_CHECK_MAX_REQUEST_ALLOWED))
- max_request_allowed = pd_is_max_request_allowed();
- else
- max_request_allowed = 1;
-
- if (IS_ENABLED(CONFIG_USB_PD_DPS) && dps_is_enabled())
- max_request_mv =
- MIN(max_request_mv, dps_get_dynamic_voltage());
-
- /*
- * If currently charging on a different port, or we are not allowed to
- * request the max voltage, then select vSafe5V
- */
- if (charging_allowed && max_request_allowed) {
- /* find pdo index for max voltage we can request */
- pdo_index = pd_find_pdo_index(src_cap_cnt, src_caps,
- max_request_mv, &pdo);
- } else {
- /* src cap 0 should be vSafe5V */
- pdo_index = 0;
- pdo = src_caps[0];
- }
-
- pd_extract_pdo_power(pdo, ma, mv, &unused);
-
- /*
- * Adjust VBUS current if CTVPD device was detected.
- */
- if (vpd_vdo > 0) {
- max_vbus = VPD_VDO_MAX_VBUS(vpd_vdo);
- vpd_vbus_dcr = VPD_VDO_VBUS_IMP(vpd_vdo) << 1;
- vpd_gnd_dcr = VPD_VDO_GND_IMP(vpd_vdo);
-
- /*
- * Valid max_vbus values:
- * 00b - 20000 mV
- * 01b - 30000 mV
- * 10b - 40000 mV
- * 11b - 50000 mV
- */
- max_vbus = 20000 + max_vbus * 10000;
- if (*mv > max_vbus)
- *mv = max_vbus;
-
- /*
- * 5000 mA cable: 150 = 750000 / 50000
- * 3000 mA cable: 250 = 750000 / 30000
- */
- if (*ma > 3000)
- *ma = 750000 / (150 + vpd_vbus_dcr + vpd_gnd_dcr);
- else
- *ma = 750000 / (250 + vpd_vbus_dcr + vpd_gnd_dcr);
- }
-
- uw = *ma * *mv;
- /* Mismatch bit set if less power offered than the operating power */
- if (uw < (1000 * PD_OPERATING_POWER_MW))
- flags |= RDO_CAP_MISMATCH;
-
-#ifdef CONFIG_USB_PD_GIVE_BACK
- /* Tell source we are give back capable. */
- flags |= RDO_GIVE_BACK;
-
- /*
- * BATTERY PDO: Inform the source that the sink will reduce
- * power to this minimum level on receipt of a GotoMin Request.
- */
- max_or_min_mw = PD_MIN_POWER_MW;
-
- /*
- * FIXED or VARIABLE PDO: Inform the source that the sink will
- * reduce current to this minimum level on receipt of a GotoMin
- * Request.
- */
- max_or_min_ma = PD_MIN_CURRENT_MA;
-#else
- /*
- * Can't give back, so set maximum current and power to
- * operating level.
- */
- max_or_min_ma = *ma;
- max_or_min_mw = uw / 1000;
-#endif
-
- if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) {
- int mw = uw / 1000;
- *rdo = RDO_BATT(pdo_index + 1, mw, max_or_min_mw, flags);
- } else {
- *rdo = RDO_FIXED(pdo_index + 1, *ma, max_or_min_ma, flags);
- }
-
- /*
- * Ref: USB Power Delivery Specification
- * (Revision 3.0, Version 2.0 / Revision 2.0, Version 1.3)
- * 6.4.2.4 USB Communications Capable
- * 6.4.2.5 No USB Suspend
- *
- * If the port partner is capable of USB communication set the
- * USB Communications Capable flag.
- * If the port partner is sink device do not suspend USB as the
- * power can be used for charging.
- */
- if (pd_get_partner_usb_comm_capable(port)) {
- *rdo |= RDO_COMM_CAP;
- if (pd_get_power_role(port) == PD_ROLE_SINK)
- *rdo |= RDO_NO_SUSPEND;
- }
-}
-
-void pd_process_source_cap(int port, int cnt, uint32_t *src_caps)
-{
- pd_set_src_caps(port, cnt, src_caps);
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) {
- uint32_t ma, mv, pdo, unused;
- uint32_t max_mv = pd_get_max_voltage();
-
- if (IS_ENABLED(CONFIG_USB_PD_DPS) && dps_is_enabled())
- max_mv = MIN(max_mv, dps_get_dynamic_voltage());
-
- /* Get max power info that we could request */
- pd_find_pdo_index(pd_get_src_cap_cnt(port),
- pd_get_src_caps(port),
- max_mv, &pdo);
- pd_extract_pdo_power(pdo, &ma, &mv, &unused);
-
- /* Set max. limit, but apply 500mA ceiling */
- charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, PD_MIN_MA);
- pd_set_input_current_limit(port, ma, mv);
- }
-}
-#endif /* defined(PD_MAX_VOLTAGE_MV) && defined(PD_OPERATING_POWER_MW) */
-
-bool pd_is_battery_capable(void)
-{
- bool capable;
-
- /* Battery is present and at some minimum percentage. */
- capable = (usb_get_battery_soc() >=
- CONFIG_USB_PD_TRY_SRC_MIN_BATT_SOC);
-
-#ifdef CONFIG_BATTERY_REVIVE_DISCONNECT
- /*
- * Not capable if the battery is in the disconnect state. The discharge
- * FET may not be enabled and so attempting being a SRC may cut off
- * our only power source at the time.
- */
- capable &= (battery_get_disconnect_state() ==
- BATTERY_NOT_DISCONNECTED);
-#elif defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \
- defined(CONFIG_BATTERY_PRESENT_GPIO)
- /*
- * When battery is cutoff in ship mode it may not be reliable to
- * check if battery is present with its state of charge.
- * Also check if battery is initialized and ready to provide power.
- */
- capable &= (battery_is_present() == BP_YES);
-#endif /* CONFIG_BATTERY_PRESENT_[CUSTOM|GPIO] */
-
- return capable;
-}
-
-#ifdef CONFIG_USB_PD_TRY_SRC
-bool pd_is_try_source_capable(void)
-{
- int i;
- uint8_t try_src = 0;
- bool new_try_src;
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- try_src |= (pd_get_dual_role(i) == PD_DRP_TOGGLE_ON);
-
- /*
- * Enable try source when dual-role toggling AND battery is capable
- * of powering the whole system.
- */
- new_try_src = (try_src && pd_is_battery_capable());
-
-#if CONFIG_DEDICATED_CHARGE_PORT_COUNT > 0
- /*
- * If a dedicated supplier is present, power is not a concern and
- * therefore allow Try.Src if we're toggling.
- */
- new_try_src = try_src && (charge_manager_get_supplier() ==
- CHARGE_SUPPLIER_DEDICATED);
-#endif /* CONFIG_DEDICATED_CHARGE_PORT_COUNT */
-
- return new_try_src;
-}
-#endif /* CONFIG_USB_PD_TRY_SRC */
-
-static int get_bbram_idx(uint8_t port)
-{
- if (port < MAX_SYSTEM_BBRAM_IDX_PD_PORTS)
- return (port + SYSTEM_BBRAM_IDX_PD0);
-
- return -1;
-}
-
-int pd_get_saved_port_flags(int port, uint8_t *flags)
-{
- if (system_get_bbram(get_bbram_idx(port), flags) != EC_SUCCESS) {
-#ifndef CHIP_HOST
- ccprintf("PD NVRAM FAIL");
-#endif
- return EC_ERROR_UNKNOWN;
- }
-
- return EC_SUCCESS;
-}
-
-static void pd_set_saved_port_flags(int port, uint8_t flags)
-{
- if (system_set_bbram(get_bbram_idx(port), flags) != EC_SUCCESS) {
-#ifndef CHIP_HOST
- ccprintf("PD NVRAM FAIL");
-#endif
- }
-}
-
-void pd_update_saved_port_flags(int port, uint8_t flag, uint8_t do_set)
-{
- uint8_t saved_flags;
-
- if (pd_get_saved_port_flags(port, &saved_flags) != EC_SUCCESS)
- return;
-
- if (do_set)
- saved_flags |= flag;
- else
- saved_flags &= ~flag;
-
- pd_set_saved_port_flags(port, saved_flags);
-}
diff --git a/common/usb_pd_host_cmd.c b/common/usb_pd_host_cmd.c
deleted file mode 100644
index 4261e8c1f0..0000000000
--- a/common/usb_pd_host_cmd.c
+++ /dev/null
@@ -1,590 +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.
- *
- * Host commands for USB-PD module.
- */
-
-#include <string.h>
-
-#include "atomic.h"
-#include "battery.h"
-#include "charge_manager.h"
-#include "console.h"
-#include "ec_commands.h"
-#include "host_command.h"
-#include "mkbp_event.h"
-#include "tcpm/tcpm.h"
-#include "usb_common.h"
-#include "usb_mux.h"
-#include "usb_pd_tcpm.h"
-#include "usb_pd.h"
-#ifdef CONFIG_COMMON_RUNTIME
-struct ec_params_usb_pd_rw_hash_entry rw_hash_table[RW_HASH_ENTRIES];
-
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#else /* CONFIG_COMMON_RUNTIME */
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif /* CONFIG_COMMON_RUNTIME */
-
-#ifdef HAS_TASK_HOSTCMD
-
-static enum ec_status hc_pd_ports(struct host_cmd_handler_args *args)
-{
- struct ec_response_usb_pd_ports *r = args->response;
-
- r->num_ports = board_get_usb_pd_port_count();
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_PORTS,
- hc_pd_ports,
- EC_VER_MASK(0));
-
-#ifdef CONFIG_HOSTCMD_RWHASHPD
-static enum ec_status
-hc_remote_rw_hash_entry(struct host_cmd_handler_args *args)
-{
- int i, idx = 0, found = 0;
- const struct ec_params_usb_pd_rw_hash_entry *p = args->params;
- static int rw_hash_next_idx;
-
- if (!p->dev_id)
- return EC_RES_INVALID_PARAM;
-
- for (i = 0; i < RW_HASH_ENTRIES; i++) {
- if (p->dev_id == rw_hash_table[i].dev_id) {
- idx = i;
- found = 1;
- break;
- }
- }
-
- if (!found) {
- idx = rw_hash_next_idx;
- rw_hash_next_idx = rw_hash_next_idx + 1;
- if (rw_hash_next_idx == RW_HASH_ENTRIES)
- rw_hash_next_idx = 0;
- }
- memcpy(&rw_hash_table[idx], p, sizeof(*p));
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_RW_HASH_ENTRY,
- hc_remote_rw_hash_entry,
- EC_VER_MASK(0));
-#endif /* CONFIG_HOSTCMD_RWHASHPD */
-
-#if defined(CONFIG_EC_CMD_PD_CHIP_INFO) && !defined(CONFIG_USB_PD_TCPC)
-static enum ec_status hc_remote_pd_chip_info(struct host_cmd_handler_args *args)
-{
- const struct ec_params_pd_chip_info *p = args->params;
- struct ec_response_pd_chip_info_v1 info;
-
- if (p->port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- if (tcpm_get_chip_info(p->port, p->live, &info))
- return EC_RES_ERROR;
-
- /*
- * Take advantage of the fact that v0 and v1 structs have the
- * same layout for v0 data. (v1 just appends data)
- */
- args->response_size =
- args->version ? sizeof(struct ec_response_pd_chip_info_v1)
- : sizeof(struct ec_response_pd_chip_info);
-
- memcpy(args->response, &info, args->response_size);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PD_CHIP_INFO,
- hc_remote_pd_chip_info,
- EC_VER_MASK(0) | EC_VER_MASK(1));
-#endif /* CONFIG_EC_CMD_PD_CHIP_INFO && !CONFIG_USB_PD_TCPC */
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-static enum ec_status hc_remote_pd_set_amode(struct host_cmd_handler_args *args)
-{
- const struct ec_params_usb_pd_set_mode_request *p = args->params;
-
- if ((p->port >= board_get_usb_pd_port_count()) ||
- (!p->svid) || (!p->opos))
- return EC_RES_INVALID_PARAM;
-
- switch (p->cmd) {
- case PD_EXIT_MODE:
- if (pd_dfp_exit_mode(p->port, TCPCI_MSG_SOP, p->svid, p->opos))
- pd_send_vdm(p->port, p->svid,
- CMD_EXIT_MODE | VDO_OPOS(p->opos), NULL, 0);
- else {
- CPRINTF("Failed exit mode\n");
- return EC_RES_ERROR;
- }
- break;
- case PD_ENTER_MODE:
- if (pd_dfp_enter_mode(p->port, TCPCI_MSG_SOP, p->svid, p->opos))
- pd_send_vdm(p->port, p->svid, CMD_ENTER_MODE |
- VDO_OPOS(p->opos), NULL, 0);
- break;
- default:
- return EC_RES_INVALID_PARAM;
- }
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_SET_AMODE,
- hc_remote_pd_set_amode,
- EC_VER_MASK(0));
-
-static enum ec_status hc_remote_pd_discovery(struct host_cmd_handler_args *args)
-{
- const uint8_t *port = args->params;
- struct ec_params_usb_pd_discovery_entry *r = args->response;
-
- if (*port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- r->vid = pd_get_identity_vid(*port);
- r->ptype = pd_get_product_type(*port);
-
- /* pid only included if vid is assigned */
- if (r->vid)
- r->pid = pd_get_identity_pid(*port);
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_DISCOVERY,
- hc_remote_pd_discovery,
- EC_VER_MASK(0));
-
-static enum ec_status hc_remote_pd_get_amode(struct host_cmd_handler_args *args)
-{
- struct svdm_amode_data *modep;
- const struct ec_params_usb_pd_get_mode_request *p = args->params;
- struct ec_params_usb_pd_get_mode_response *r = args->response;
-
- if (p->port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- /* no more to send */
- /* TODO(b/148528713): Use TCPMv2's separate storage for SOP'. */
- if (p->svid_idx >= pd_get_svid_count(p->port, TCPCI_MSG_SOP)) {
- r->svid = 0;
- args->response_size = sizeof(r->svid);
- return EC_RES_SUCCESS;
- }
-
- r->svid = pd_get_svid(p->port, p->svid_idx, TCPCI_MSG_SOP);
- r->opos = 0;
- memcpy(r->vdo, pd_get_mode_vdo(p->port, p->svid_idx, TCPCI_MSG_SOP),
- sizeof(uint32_t) * PDO_MODES);
- modep = pd_get_amode_data(p->port, TCPCI_MSG_SOP, r->svid);
-
- if (modep)
- r->opos = pd_alt_mode(p->port, TCPCI_MSG_SOP, r->svid);
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_GET_AMODE,
- hc_remote_pd_get_amode,
- EC_VER_MASK(0));
-
-#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
-
-#ifdef CONFIG_COMMON_RUNTIME
-static enum ec_status hc_remote_pd_dev_info(struct host_cmd_handler_args *args)
-{
- const uint8_t *port = args->params;
- struct ec_params_usb_pd_rw_hash_entry *r = args->response;
- uint16_t dev_id;
- uint32_t current_image;
-
- if (*port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- pd_dev_get_rw_hash(*port, &dev_id, r->dev_rw_hash, &current_image);
-
- r->dev_id = dev_id;
- r->current_image = current_image;
-
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_DEV_INFO,
- hc_remote_pd_dev_info,
- EC_VER_MASK(0));
-
-static const enum pd_dual_role_states dual_role_map[USB_PD_CTRL_ROLE_COUNT] = {
- [USB_PD_CTRL_ROLE_TOGGLE_ON] = PD_DRP_TOGGLE_ON,
- [USB_PD_CTRL_ROLE_TOGGLE_OFF] = PD_DRP_TOGGLE_OFF,
- [USB_PD_CTRL_ROLE_FORCE_SINK] = PD_DRP_FORCE_SINK,
- [USB_PD_CTRL_ROLE_FORCE_SOURCE] = PD_DRP_FORCE_SOURCE,
- [USB_PD_CTRL_ROLE_FREEZE] = PD_DRP_FREEZE,
-};
-
-static const mux_state_t typec_mux_map[USB_PD_CTRL_MUX_COUNT] = {
- [USB_PD_CTRL_MUX_NONE] = USB_PD_MUX_NONE,
- [USB_PD_CTRL_MUX_USB] = USB_PD_MUX_USB_ENABLED,
- [USB_PD_CTRL_MUX_AUTO] = USB_PD_MUX_DP_ENABLED,
- [USB_PD_CTRL_MUX_DP] = USB_PD_MUX_DP_ENABLED,
- [USB_PD_CTRL_MUX_DOCK] = USB_PD_MUX_DOCK,
-};
-
-/*
- * Combines the following information into a single byte
- * Bit 0: Active/Passive cable
- * Bit 1: Optical/Non-optical cable
- * Bit 2: Legacy Thunderbolt adapter
- * Bit 3: Active Link Uni-Direction/Bi-Direction
- */
-static uint8_t get_pd_control_flags(int port)
-{
- union tbt_mode_resp_cable cable_resp;
- union tbt_mode_resp_device device_resp;
- uint8_t control_flags = 0;
-
- if (!IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- return 0;
-
- cable_resp.raw_value = pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME);
- device_resp.raw_value = pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP);
-
- /*
- * Ref: USB Type-C Cable and Connector Specification
- * Table F-11 TBT3 Cable Discover Mode VDO Responses
- * For Passive cables, Active Cable Plug link training is set to 0
- */
- control_flags |= (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE ||
- cable_resp.tbt_active_passive == TBT_CABLE_ACTIVE) ?
- USB_PD_CTRL_ACTIVE_CABLE : 0;
- control_flags |= cable_resp.tbt_cable == TBT_CABLE_OPTICAL ?
- USB_PD_CTRL_OPTICAL_CABLE : 0;
- control_flags |= device_resp.tbt_adapter == TBT_ADAPTER_TBT2_LEGACY ?
- USB_PD_CTRL_TBT_LEGACY_ADAPTER : 0;
- control_flags |= cable_resp.lsrx_comm == UNIDIR_LSRX_COMM ?
- USB_PD_CTRL_ACTIVE_LINK_UNIDIR : 0;
-
- return control_flags;
-}
-
-static uint8_t pd_get_role_flags(int port)
-{
- return (pd_get_power_role(port) == PD_ROLE_SOURCE ?
- PD_CTRL_RESP_ROLE_POWER : 0) |
- (pd_get_data_role(port) == PD_ROLE_DFP ?
- PD_CTRL_RESP_ROLE_DATA : 0) |
- (pd_get_vconn_state(port) ?
- PD_CTRL_RESP_ROLE_VCONN : 0) |
- (pd_get_partner_dual_role_power(port) ?
- PD_CTRL_RESP_ROLE_DR_POWER : 0) |
- (pd_get_partner_data_swap_capable(port) ?
- PD_CTRL_RESP_ROLE_DR_DATA : 0) |
- (pd_get_partner_usb_comm_capable(port) ?
- PD_CTRL_RESP_ROLE_USB_COMM : 0) |
- (pd_get_partner_unconstr_power(port) ?
- PD_CTRL_RESP_ROLE_UNCONSTRAINED : 0);
-}
-
-static enum ec_status hc_usb_pd_control(struct host_cmd_handler_args *args)
-{
- const struct ec_params_usb_pd_control *p = args->params;
- struct ec_response_usb_pd_control_v2 *r_v2 = args->response;
- struct ec_response_usb_pd_control_v1 *r_v1 = args->response;
- struct ec_response_usb_pd_control *r = args->response;
- const char *task_state_name;
-
- if (p->port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- if (p->role >= USB_PD_CTRL_ROLE_COUNT ||
- p->mux >= USB_PD_CTRL_MUX_COUNT)
- return EC_RES_INVALID_PARAM;
-
- if (p->role != USB_PD_CTRL_ROLE_NO_CHANGE) {
- if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE))
- pd_set_dual_role(p->port, dual_role_map[p->role]);
- else
- return EC_RES_INVALID_PARAM;
- }
-
- if (IS_ENABLED(CONFIG_USBC_SS_MUX) &&
- p->mux != USB_PD_CTRL_MUX_NO_CHANGE)
- usb_mux_set(p->port, typec_mux_map[p->mux],
- typec_mux_map[p->mux] == USB_PD_MUX_NONE ?
- USB_SWITCH_DISCONNECT :
- USB_SWITCH_CONNECT,
- polarity_rm_dts(pd_get_polarity(p->port)));
-
- if (p->swap == USB_PD_CTRL_SWAP_DATA) {
- pd_request_data_swap(p->port);
- } else if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE)) {
- if (p->swap == USB_PD_CTRL_SWAP_POWER)
- pd_request_power_swap(p->port);
- else if (IS_ENABLED(CONFIG_USBC_VCONN_SWAP) &&
- p->swap == USB_PD_CTRL_SWAP_VCONN)
- pd_request_vconn_swap(p->port);
- }
-
- switch (args->version) {
- case 0:
- r->enabled = pd_comm_is_enabled(p->port);
- r->polarity = pd_get_polarity(p->port);
- r->role = pd_get_power_role(p->port);
- r->state = pd_get_task_state(p->port);
- args->response_size = sizeof(*r);
- break;
- case 1:
- case 2:
- r_v2->enabled =
- (pd_comm_is_enabled(p->port) ?
- PD_CTRL_RESP_ENABLED_COMMS : 0) |
- (pd_is_connected(p->port) ?
- PD_CTRL_RESP_ENABLED_CONNECTED : 0) |
- (pd_capable(p->port) ?
- PD_CTRL_RESP_ENABLED_PD_CAPABLE : 0);
- r_v2->role = pd_get_role_flags(p->port);
- r_v2->polarity = pd_get_polarity(p->port);
-
- r_v2->cc_state = pd_get_task_cc_state(p->port);
- task_state_name = pd_get_task_state_name(p->port);
- if (task_state_name)
- strzcpy(r_v2->state, task_state_name,
- sizeof(r_v2->state));
- else
- r_v2->state[0] = '\0';
-
- r_v2->control_flags = get_pd_control_flags(p->port);
- if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
- r_v2->dp_mode = get_dp_pin_mode(p->port);
- r_v2->cable_speed = get_tbt_cable_speed(p->port);
- r_v2->cable_gen = get_tbt_rounded_support(p->port);
- }
-
- if (args->version == 1)
- args->response_size = sizeof(*r_v1);
- else
- args->response_size = sizeof(*r_v2);
-
- break;
- default:
- return EC_RES_INVALID_PARAM;
- }
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_CONTROL,
- hc_usb_pd_control,
- EC_VER_MASK(0) | EC_VER_MASK(1) | EC_VER_MASK(2));
-#endif /* CONFIG_COMMON_RUNTIME */
-
-#if defined(CONFIG_HOSTCMD_FLASHPD) && defined(CONFIG_USB_PD_TCPMV2)
-static enum ec_status hc_remote_flash(struct host_cmd_handler_args *args)
-{
- const struct ec_params_usb_pd_fw_update *p = args->params;
- int port = p->port;
- int rv = EC_RES_SUCCESS;
- const uint32_t *data = &(p->size) + 1;
- int i, size;
-
- if (port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- if (p->size + sizeof(*p) > args->params_size)
- return EC_RES_INVALID_PARAM;
-
-#if defined(CONFIG_CHARGE_MANAGER) && defined(CONFIG_BATTERY) && \
- (defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \
- defined(CONFIG_BATTERY_PRESENT_GPIO))
- /*
- * Do not allow PD firmware update if no battery and this port
- * is sinking power, because we will lose power.
- */
- if (battery_is_present() != BP_YES &&
- charge_manager_get_active_charge_port() == port)
- return EC_RES_UNAVAILABLE;
-#endif
-
- switch (p->cmd) {
- case USB_PD_FW_REBOOT:
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_REBOOT, NULL, 0);
- /*
- * Return immediately to free pending i2c bus. Host needs to
- * manage this delay.
- */
- return EC_RES_SUCCESS;
-
- case USB_PD_FW_FLASH_ERASE:
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_ERASE, NULL, 0);
- /*
- * Return immediately. Host needs to manage delays here which
- * can be as long as 1.2 seconds on 64KB RW flash.
- */
- return EC_RES_SUCCESS;
-
- case USB_PD_FW_ERASE_SIG:
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_ERASE_SIG, NULL, 0);
- break;
-
- case USB_PD_FW_FLASH_WRITE:
- /* Data size must be a multiple of 4 */
- if (!p->size || p->size % 4)
- return EC_RES_INVALID_PARAM;
-
- size = p->size / 4;
- for (i = 0; i < size; i += VDO_MAX_SIZE - 1) {
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_WRITE,
- data + i, MIN(size - i, VDO_MAX_SIZE - 1));
- }
- return EC_RES_SUCCESS;
-
- default:
- return EC_RES_INVALID_PARAM;
- }
-
- return rv;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_FW_UPDATE,
- hc_remote_flash,
- EC_VER_MASK(0));
-#endif /* CONFIG_HOSTCMD_FLASHPD && CONFIG_USB_PD_TCPMV2 */
-
-#ifdef CONFIG_MKBP_EVENT
-__overridable void pd_notify_dp_alt_mode_entry(int port)
-{
- (void)port;
- CPRINTS("Notifying AP of DP Alt Mode Entry...");
- mkbp_send_event(EC_MKBP_EVENT_DP_ALT_MODE_ENTERED);
-}
-#endif /* CONFIG_MKBP_EVENT */
-
-__overridable enum ec_pd_port_location board_get_pd_port_location(int port)
-{
- (void)port;
- return EC_PD_PORT_LOCATION_UNKNOWN;
-}
-
-static enum ec_status hc_get_pd_port_caps(struct host_cmd_handler_args *args)
-{
- const struct ec_params_get_pd_port_caps *p = args->params;
- struct ec_response_get_pd_port_caps *r = args->response;
-
- if (p->port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- /* Power Role */
- if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE))
- r->pd_power_role_cap = EC_PD_POWER_ROLE_DUAL;
- else
- r->pd_power_role_cap = EC_PD_POWER_ROLE_SINK;
-
- /* Try-Power Role */
- if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC))
- r->pd_try_power_role_cap = EC_PD_TRY_POWER_ROLE_SOURCE;
- else
- r->pd_try_power_role_cap = EC_PD_TRY_POWER_ROLE_NONE;
-
- if (IS_ENABLED(CONFIG_USB_VPD) ||
- IS_ENABLED(CONFIG_USB_CTVPD))
- r->pd_data_role_cap = EC_PD_DATA_ROLE_UFP;
- else
- r->pd_data_role_cap = EC_PD_DATA_ROLE_DUAL;
-
- /* Allow boards to override the locations from UNKNOWN if desired */
- r->pd_port_location = board_get_pd_port_location(p->port);
-
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_GET_PD_PORT_CAPS,
- hc_get_pd_port_caps,
- EC_VER_MASK(0));
-
-#ifdef CONFIG_HOSTCMD_PD_CONTROL
-static enum ec_status pd_control(struct host_cmd_handler_args *args)
-{
- static int pd_control_disabled[CONFIG_USB_PD_PORT_MAX_COUNT];
- const struct ec_params_pd_control *cmd = args->params;
- int enable = 0;
-
- if (cmd->chip >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- /* Always allow disable command */
- if (cmd->subcmd == PD_CONTROL_DISABLE) {
- pd_control_disabled[cmd->chip] = 1;
- return EC_RES_SUCCESS;
- }
-
- if (pd_control_disabled[cmd->chip])
- return EC_RES_ACCESS_DENIED;
-
- if (cmd->subcmd == PD_SUSPEND) {
- if (!pd_firmware_upgrade_check_power_readiness(cmd->chip))
- return EC_RES_BUSY;
- enable = 0;
- } else if (cmd->subcmd == PD_RESUME) {
- enable = 1;
- } else if (cmd->subcmd == PD_RESET) {
-#ifdef HAS_TASK_PDCMD
- board_reset_pd_mcu();
-#else
- return EC_RES_INVALID_COMMAND;
-#endif
- } else if (cmd->subcmd == PD_CHIP_ON && board_set_tcpc_power_mode) {
- board_set_tcpc_power_mode(cmd->chip, 1);
- return EC_RES_SUCCESS;
- } else {
- return EC_RES_INVALID_COMMAND;
- }
-
- pd_comm_enable(cmd->chip, enable);
- pd_set_suspend(cmd->chip, !enable);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PD_CONTROL, pd_control, EC_VER_MASK(0));
-#endif /* CONFIG_HOSTCMD_PD_CONTROL */
-
-#if !defined(CONFIG_USB_PD_TCPM_STUB) && !defined(TEST_BUILD)
-/*
- * PD host event status for host command
- * 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 enum ec_status
-hc_pd_host_event_status(struct host_cmd_handler_args *args)
-{
- struct ec_response_host_event_status *r = args->response;
-
- /* Read and clear the host event status to return to AP */
- r->status = atomic_clear(&pd_host_event_status);
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PD_HOST_EVENT_STATUS, hc_pd_host_event_status,
- EC_VER_MASK(0));
-
-/* Send host event up to AP */
-void pd_send_host_event(int mask)
-{
- /* mask must be set */
- if (!mask)
- return;
-
- atomic_or(&pd_host_event_status, mask);
- /* interrupt the AP */
- host_set_single_event(EC_HOST_EVENT_PD_MCU);
-}
-#endif /* ! CONFIG_USB_PD_TCPM_STUB && ! TEST_BUILD */
-
-#endif /* HAS_TASK_HOSTCMD */
diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c
deleted file mode 100644
index de6fc63a60..0000000000
--- a/common/usb_pd_policy.c
+++ /dev/null
@@ -1,969 +0,0 @@
-/* Copyright 2014 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.
- */
-
-#include "atomic.h"
-#include "charge_manager.h"
-#include "common.h"
-#include "console.h"
-#include "cros_version.h"
-#include "ec_commands.h"
-#include "flash.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "mkbp_event.h"
-#include "registers.h"
-#include "rsa.h"
-#include "sha256.h"
-#include "system.h"
-#include "task.h"
-#include "tcpm/tcpm.h"
-#include "timer.h"
-#include "util.h"
-#include "usb_api.h"
-#include "usb_common.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
-#include "usbc_ppc.h"
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args)
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args)
-#else
-#define CPRINTS(format, args...)
-#define CPRINTF(format, args...)
-#endif
-
-/*
- * This file is currently only used for TCPMv1, and would need changes before
- * being used for TCPMv2. One example: PD_FLAGS_* are TCPMv1 only.
- */
-#ifndef CONFIG_USB_PD_TCPMV1
-#error This file must only be used with TCPMv1
-#endif
-
-static int rw_flash_changed = 1;
-
-__overridable void pd_check_pr_role(int port, enum pd_power_role pr_role,
- int flags)
-{
- /*
- * If partner is dual-role power and dualrole toggling is on, consider
- * if a power swap is necessary.
- */
- if ((flags & PD_FLAGS_PARTNER_DR_POWER) &&
- pd_get_dual_role(port) == PD_DRP_TOGGLE_ON) {
- /*
- * If we are a sink and partner is not unconstrained, then
- * swap to become a source. If we are source and partner is
- * unconstrained, swap to become a sink.
- */
- int partner_unconstrained = flags & PD_FLAGS_PARTNER_UNCONSTR;
-
- if ((!partner_unconstrained && pr_role == PD_ROLE_SINK) ||
- (partner_unconstrained && pr_role == PD_ROLE_SOURCE))
- pd_request_power_swap(port);
- }
-}
-
-__overridable void pd_check_dr_role(int port, enum pd_data_role dr_role,
- int flags)
-{
- /* If UFP, try to switch to DFP */
- if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_UFP)
- pd_request_data_swap(port);
-}
-
-#ifdef CONFIG_MKBP_EVENT
-static int dp_alt_mode_entry_get_next_event(uint8_t *data)
-{
- return EC_SUCCESS;
-}
-DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_DP_ALT_MODE_ENTERED,
- dp_alt_mode_entry_get_next_event);
-#endif /* CONFIG_MKBP_EVENT */
-
-/* Last received source cap */
-static uint32_t pd_src_caps[CONFIG_USB_PD_PORT_MAX_COUNT][PDO_MAX_OBJECTS];
-static uint8_t pd_src_cap_cnt[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-const uint32_t * const pd_get_src_caps(int port)
-{
- return pd_src_caps[port];
-}
-
-void pd_set_src_caps(int port, int cnt, uint32_t *src_caps)
-{
- int i;
-
- pd_src_cap_cnt[port] = cnt;
-
- for (i = 0; i < cnt; i++)
- pd_src_caps[port][i] = *src_caps++;
-}
-
-uint8_t pd_get_src_cap_cnt(int port)
-{
- return pd_src_cap_cnt[port];
-}
-
-static struct pd_cable cable[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-enum pd_rev_type get_usb_pd_cable_revision(int port)
-{
- return cable[port].rev;
-}
-
-bool consume_sop_prime_repeat_msg(int port, uint8_t msg_id)
-{
- if (cable[port].last_sop_p_msg_id != msg_id) {
- cable[port].last_sop_p_msg_id = msg_id;
- return false;
- }
- CPRINTF("C%d SOP Prime repeat msg_id %d\n", port, msg_id);
- return true;
-}
-
-bool consume_sop_prime_prime_repeat_msg(int port, uint8_t msg_id)
-{
- if (cable[port].last_sop_p_p_msg_id != msg_id) {
- cable[port].last_sop_p_p_msg_id = msg_id;
- return false;
- }
- CPRINTF("C%d SOP Prime Prime repeat msg_id %d\n", port, msg_id);
- return true;
-}
-
-__maybe_unused static uint8_t is_sop_prime_ready(int port)
-{
- /*
- * Ref: USB PD 3.0 sec 2.5.4: When an Explicit Contract is in place the
- * VCONN Source (either the DFP or the UFP) can communicate with the
- * Cable Plug(s) using SOP’/SOP’’ Packets
- *
- * Ref: USB PD 2.0 sec 2.4.4: When an Explicit Contract is in place the
- * DFP (either the Source or the Sink) can communicate with the
- * Cable Plug(s) using SOP’/SOP” Packets.
- * Sec 3.6.11 : Before communicating with a Cable Plug a Port Should
- * ensure that it is the Vconn Source
- */
- return (pd_get_vconn_state(port) &&
- (IS_ENABLED(CONFIG_USB_PD_REV30) ||
- (pd_get_data_role(port) == PD_ROLE_DFP)));
-}
-
-void reset_pd_cable(int port)
-{
- memset(&cable[port], 0, sizeof(cable[port]));
- cable[port].last_sop_p_msg_id = INVALID_MSG_ID_COUNTER;
- cable[port].last_sop_p_p_msg_id = INVALID_MSG_ID_COUNTER;
-}
-
-bool should_enter_usb4_mode(int port)
-{
- return IS_ENABLED(CONFIG_USB_PD_USB4) &&
- cable[port].flags & CABLE_FLAGS_ENTER_USB_MODE;
-}
-
-void enable_enter_usb4_mode(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_USB4))
- cable[port].flags |= CABLE_FLAGS_ENTER_USB_MODE;
-}
-
-void disable_enter_usb4_mode(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_USB4))
- cable[port].flags &= ~CABLE_FLAGS_ENTER_USB_MODE;
-}
-
-#ifdef CONFIG_USB_PD_ALT_MODE
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-
-static struct pd_discovery discovery[CONFIG_USB_PD_PORT_MAX_COUNT]
- [DISCOVERY_TYPE_COUNT];
-static struct partner_active_modes partner_amodes[CONFIG_USB_PD_PORT_MAX_COUNT]
- [AMODE_TYPE_COUNT];
-
-static bool is_vdo_present(int cnt, int index)
-{
- return cnt > index;
-}
-
-static bool is_modal(int port, int cnt, const uint32_t *payload)
-{
- return is_vdo_present(cnt, VDO_INDEX_IDH) &&
- PD_IDH_IS_MODAL(payload[VDO_INDEX_IDH]);
-}
-
-static bool is_tbt_compat_mode(int port, int cnt, const uint32_t *payload)
-{
- /*
- * Ref: USB Type-C cable and connector specification
- * F.2.5 TBT3 Device Discover Mode Responses
- */
- return is_vdo_present(cnt, VDO_INDEX_IDH) &&
- PD_VDO_RESP_MODE_INTEL_TBT(payload[VDO_INDEX_IDH]);
-}
-
-static bool cable_supports_tbt_speed(int port)
-{
- enum tbt_compat_cable_speed tbt_cable_speed = get_tbt_cable_speed(port);
-
- return (tbt_cable_speed == TBT_SS_TBT_GEN3 ||
- tbt_cable_speed == TBT_SS_U32_GEN1_GEN2);
-}
-
-static bool is_tbt_compat_enabled(int port)
-{
- return (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) &&
- (cable[port].flags & CABLE_FLAGS_TBT_COMPAT_ENABLE));
-}
-
-static void enable_tbt_compat_mode(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE))
- cable[port].flags |= CABLE_FLAGS_TBT_COMPAT_ENABLE;
-}
-
-static inline void disable_tbt_compat_mode(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE))
- cable[port].flags &= ~CABLE_FLAGS_TBT_COMPAT_ENABLE;
-}
-
-static inline void limit_tbt_cable_speed(int port)
-{
- /* Cable flags are cleared when cable reset is called */
- cable[port].flags |= CABLE_FLAGS_TBT_COMPAT_LIMIT_SPEED;
-}
-
-static inline bool is_limit_tbt_cable_speed(int port)
-{
- return !!(cable[port].flags & CABLE_FLAGS_TBT_COMPAT_LIMIT_SPEED);
-}
-
-static bool is_intel_svid(int port, enum tcpci_msg_type type)
-{
- int i;
-
- for (i = 0; i < discovery[port][type].svid_cnt; i++) {
- if (pd_get_svid(port, i, type) == USB_VID_INTEL)
- return true;
- }
-
- return false;
-}
-
-static inline bool is_usb4_mode_enabled(int port)
-{
- return (IS_ENABLED(CONFIG_USB_PD_USB4) &&
- (cable[port].flags & CABLE_FLAGS_USB4_CAPABLE));
-}
-
-static inline void enable_usb4_mode(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_USB4))
- cable[port].flags |= CABLE_FLAGS_USB4_CAPABLE;
-}
-
-static inline void disable_usb4_mode(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_USB4))
- cable[port].flags &= ~CABLE_FLAGS_USB4_CAPABLE;
-}
-
-/*
- * Ref: USB Type-C Cable and Connector Specification
- * Figure 5-1 USB4 Discovery and Entry Flow Model.
- *
- * Note: USB Type-C Cable and Connector Specification
- * doesn't include details for Revision 2 cables.
- *
- * Passive Cable
- * |
- * -----------------------------------
- * | |
- * Revision 2 Revision 3
- * USB Signalling USB Signalling
- * | |
- * ------------------ -------------------------
- * | | | | | | |
- * USB2.0 USB3.1 USB3.1 USB3.2 USB4 USB3.2 USB2
- * | Gen1 Gen1 Gen2 Gen2 Gen3 Gen1 |
- * | | | | | | Exit
- * -------- ------------ -------- USB4
- * | | | Discovery.
- * Exit Is DFP Gen3 Capable? Enter USB4
- * USB4 | with respective
- * Discovery. --- No ---|--- Yes --- cable speed.
- * | |
- * Enter USB4 with Is Cable TBT3
- * respective cable |
- * speed. --- No ---|--- Yes ---
- * | |
- * Enter USB4 with Enter USB4 with
- * TBT Gen2 passive TBT Gen3 passive
- * cable. cable.
- *
- */
-static bool is_cable_ready_to_enter_usb4(int port, int cnt)
-{
- /* TODO: USB4 enter mode for Active cables */
- struct pd_discovery *disc = &discovery[port][TCPCI_MSG_SOP_PRIME];
- if (IS_ENABLED(CONFIG_USB_PD_USB4) &&
- (get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE) &&
- is_vdo_present(cnt, VDO_INDEX_PTYPE_CABLE1)) {
- switch (cable[port].rev) {
- case PD_REV30:
- switch (disc->identity.product_t1.p_rev30.ss) {
- case USB_R30_SS_U40_GEN3:
- case USB_R30_SS_U32_U40_GEN1:
- return true;
- case USB_R30_SS_U32_U40_GEN2:
- /* Check if DFP is Gen 3 capable */
- if (IS_ENABLED(CONFIG_USB_PD_TBT_GEN3_CAPABLE))
- return false;
- return true;
- default:
- disable_usb4_mode(port);
- return false;
- }
- case PD_REV20:
- switch (disc->identity.product_t1.p_rev20.ss) {
- case USB_R20_SS_U31_GEN1_GEN2:
- /* Check if DFP is Gen 3 capable */
- if (IS_ENABLED(CONFIG_USB_PD_TBT_GEN3_CAPABLE))
- return false;
- return true;
- default:
- disable_usb4_mode(port);
- return false;
- }
- default:
- disable_usb4_mode(port);
- }
- }
- return false;
-}
-
-void pd_dfp_discovery_init(int port)
-{
- memset(&discovery[port], 0, sizeof(struct pd_discovery));
-}
-
-void pd_dfp_mode_init(int port)
-{
- memset(&partner_amodes[port], 0, sizeof(partner_amodes[0]));
-}
-
-static int dfp_discover_ident(uint32_t *payload)
-{
- payload[0] = VDO(USB_SID_PD, 1, CMD_DISCOVER_IDENT);
- return 1;
-}
-
-static int dfp_discover_svids(uint32_t *payload)
-{
- payload[0] = VDO(USB_SID_PD, 1, CMD_DISCOVER_SVID);
- return 1;
-}
-
-struct pd_discovery *pd_get_am_discovery_and_notify_access(
- int port, enum tcpci_msg_type type)
-{
- return (struct pd_discovery *)pd_get_am_discovery(port, type);
-}
-
-const struct pd_discovery *pd_get_am_discovery(int port,
- enum tcpci_msg_type type)
-{
- return &discovery[port][type];
-}
-
-struct partner_active_modes *
-pd_get_partner_active_modes(int port, enum tcpci_msg_type type)
-{
- assert(type < AMODE_TYPE_COUNT);
- return &partner_amodes[port][type];
-}
-
-/* Note: Enter mode flag is not needed by TCPMv1 */
-void pd_set_dfp_enter_mode_flag(int port, bool set)
-{
-}
-
-/**
- * Return the discover alternate mode payload data
- *
- * @param port USB-C port number
- * @param payload Pointer to payload data to fill
- * @return 1 if valid SVID present else 0
- */
-static int dfp_discover_modes(int port, uint32_t *payload)
-{
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP);
- uint16_t svid = disc->svids[disc->svid_idx].svid;
-
- if (disc->svid_idx >= disc->svid_cnt)
- return 0;
-
- payload[0] = VDO(svid, 1, CMD_DISCOVER_MODES);
-
- return 1;
-}
-
-static bool is_usb4_vdo(int port, int cnt, uint32_t *payload)
-{
- enum idh_ptype ptype = PD_IDH_PTYPE(payload[VDO_I(IDH)]);
-
- if (IS_PD_IDH_UFP_PTYPE(ptype)) {
- /*
- * Ref: USB Type-C Cable and Connector Specification
- * Figure 5-1 USB4 Discovery and Entry Flow Model
- * Device USB4 VDO detection.
- */
- return IS_ENABLED(CONFIG_USB_PD_USB4) &&
- is_vdo_present(cnt, VDO_INDEX_PTYPE_UFP1_VDO) &&
- PD_PRODUCT_IS_USB4(payload[VDO_INDEX_PTYPE_UFP1_VDO]);
- }
- return false;
-}
-
-static int process_am_discover_ident_sop(int port, int cnt, uint32_t head,
- uint32_t *payload,
- enum tcpci_msg_type *rtype)
-{
- pd_dfp_discovery_init(port);
- pd_dfp_mode_init(port);
- dfp_consume_identity(port, TCPCI_MSG_SOP, cnt, payload);
-
- if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP) && is_sop_prime_ready(port) &&
- board_is_tbt_usb4_port(port)) {
- /* Enable USB4 mode if USB4 VDO present and port partner
- * supports USB Rev 3.0.
- */
- if (is_usb4_vdo(port, cnt, payload) &&
- PD_HEADER_REV(head) == PD_REV30)
- enable_usb4_mode(port);
-
- /*
- * Enable Thunderbolt-compatible mode if the modal operation is
- * supported.
- */
- if (is_modal(port, cnt, payload))
- enable_tbt_compat_mode(port);
-
- if (is_modal(port, cnt, payload) ||
- is_usb4_vdo(port, cnt, payload)) {
- *rtype = TCPCI_MSG_SOP_PRIME;
- return dfp_discover_ident(payload);
- }
- }
-
- return dfp_discover_svids(payload);
-}
-
-static int process_am_discover_ident_sop_prime(int port, int cnt, uint32_t head,
- uint32_t *payload)
-{
- dfp_consume_identity(port, TCPCI_MSG_SOP_PRIME, cnt, payload);
- cable[port].rev = PD_HEADER_REV(head);
-
- /*
- * Enter USB4 mode if the cable supports USB4 operation and has USB4
- * VDO.
- */
- if (is_usb4_mode_enabled(port) &&
- is_cable_ready_to_enter_usb4(port, cnt)) {
- enable_enter_usb4_mode(port);
- usb_mux_set_safe_mode(port);
- /*
- * To change the mode of operation from USB4 the port needs to
- * be reconfigured.
- * Ref: USB Type-C Cable and Connectot Spec section 5.4.4.
- */
- disable_tbt_compat_mode(port);
- return 0;
- }
-
- /*
- * Disable Thunderbolt-compatible mode if the cable does not support
- * superspeed.
- */
- if (is_tbt_compat_enabled(port) &&
- get_tbt_cable_speed(port) < TBT_SS_U31_GEN1)
- disable_tbt_compat_mode(port);
-
- return dfp_discover_svids(payload);
-}
-
-static int process_am_discover_svids(int port, int cnt, uint32_t *payload,
- enum tcpci_msg_type sop,
- enum tcpci_msg_type *rtype)
-{
- /*
- * The pd_discovery structure stores SOP and SOP' discovery results
- * separately, but TCPMv1 depends on one-dimensional storage of SVIDs
- * and modes. Therefore, always use TCPCI_MSG_SOP in TCPMv1.
- */
- dfp_consume_svids(port, sop, cnt, payload);
-
- /*
- * Ref: USB Type-C Cable and Connector Specification,
- * figure F-1: TBT3 Discovery Flow
- *
- * For USB4 mode if device or cable doesn't have Intel SVID,
- * disable Thunderbolt-Compatible mode directly enter USB4 mode
- * with USB3.2 Gen1/Gen2 speed.
- *
- * For Thunderbolt-compatible, check if 0x8087 is received for
- * Discover SVID SOP. If not, disable Thunderbolt-compatible mode
- *
- * If 0x8087 is not received for Discover SVID SOP' limit to TBT
- * passive Gen 2 cable.
- */
- if (is_tbt_compat_enabled(port)) {
- bool intel_svid = is_intel_svid(port, sop);
- if (!intel_svid) {
- if (is_usb4_mode_enabled(port)) {
- disable_tbt_compat_mode(port);
- cable[port].cable_mode_resp.tbt_cable_speed =
- TBT_SS_U32_GEN1_GEN2;
- enable_enter_usb4_mode(port);
- usb_mux_set_safe_mode(port);
- return 0;
- }
-
- if (sop == TCPCI_MSG_SOP_PRIME)
- limit_tbt_cable_speed(port);
- else
- disable_tbt_compat_mode(port);
- } else if (sop == TCPCI_MSG_SOP) {
- *rtype = TCPCI_MSG_SOP_PRIME;
- return dfp_discover_svids(payload);
- }
- }
-
- return dfp_discover_modes(port, payload);
-}
-
-static int process_tbt_compat_discover_modes(int port,
- enum tcpci_msg_type sop,
- uint32_t *payload,
- enum tcpci_msg_type *rtype)
-{
- int rsize;
-
- /* Initialize transmit type to SOP */
- *rtype = TCPCI_MSG_SOP;
-
- /*
- * For active cables, Enter mode: SOP', SOP'', SOP
- * Ref: USB Type-C Cable and Connector Specification, figure F-1: TBT3
- * Discovery Flow and Section F.2.7 TBT3 Cable Enter Mode Command.
- */
- if (sop == TCPCI_MSG_SOP_PRIME) {
- /* Store Discover Mode SOP' response */
- cable[port].cable_mode_resp.raw_value = payload[1];
-
- if (is_usb4_mode_enabled(port)) {
- /*
- * If Cable is not Thunderbolt Gen 3
- * capable or Thunderbolt Gen1_Gen2
- * capable, disable USB4 mode and
- * continue flow for
- * Thunderbolt-compatible mode
- */
- if (cable_supports_tbt_speed(port)) {
- enable_enter_usb4_mode(port);
- usb_mux_set_safe_mode(port);
- return 0;
- }
- disable_usb4_mode(port);
- }
-
- /*
- * Send TBT3 Cable Enter Mode (SOP') for active cables,
- * otherwise send TBT3 Device Enter Mode (SOP).
- */
- if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE)
- *rtype = TCPCI_MSG_SOP_PRIME;
-
- rsize = enter_tbt_compat_mode(port, *rtype, payload);
- } else {
- /* Store Discover Mode SOP response */
- cable[port].dev_mode_resp.raw_value = payload[1];
-
- if (is_limit_tbt_cable_speed(port)) {
- /*
- * Passive cable has Nacked for Discover SVID.
- * No need to do Discover modes of cable.
- * Enter into device Thunderbolt-compatible mode.
- */
- rsize = enter_tbt_compat_mode(port, *rtype, payload);
- } else {
- /* Discover modes for SOP' */
- discovery[port][TCPCI_MSG_SOP].svid_idx--;
- rsize = dfp_discover_modes(port, payload);
- *rtype = TCPCI_MSG_SOP_PRIME;
- }
- }
-
- return rsize;
-}
-
-static int obj_cnt_enter_tbt_compat_mode(int port, enum tcpci_msg_type sop,
- uint32_t *payload,
- enum tcpci_msg_type *rtype)
-{
- struct pd_discovery *disc = &discovery[port][TCPCI_MSG_SOP_PRIME];
-
- /* Enter mode SOP' for active cables */
- if (sop == TCPCI_MSG_SOP_PRIME) {
- /* Check if the cable has a SOP'' controller */
- if (disc->identity.product_t1.a_rev20.sop_p_p)
- *rtype = TCPCI_MSG_SOP_PRIME_PRIME;
- return enter_tbt_compat_mode(port, *rtype, payload);
- }
-
- /* Enter Mode SOP'' for active cables with SOP'' controller */
- if (sop == TCPCI_MSG_SOP_PRIME_PRIME)
- return enter_tbt_compat_mode(port, *rtype, payload);
-
- /* Update Mux state to Thunderbolt-compatible mode. */
- set_tbt_compat_mode_ready(port);
- /* No response once device (and cable) acks */
- return 0;
-}
-#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
-
-int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload,
- uint32_t head, enum tcpci_msg_type *rtype)
-{
- int cmd = PD_VDO_CMD(payload[0]);
- int cmd_type = PD_VDO_CMDT(payload[0]);
- int (*func)(int port, uint32_t *payload) = NULL;
-
- int rsize = 1; /* VDM header at a minimum */
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- enum tcpci_msg_type sop = PD_HEADER_GET_SOP(head);
-#endif
-
- /* Transmit SOP messages by default */
- *rtype = TCPCI_MSG_SOP;
-
- payload[0] &= ~VDO_CMDT_MASK;
- *rpayload = payload;
-
- if (cmd_type == CMDT_INIT) {
- switch (cmd) {
- case CMD_DISCOVER_IDENT:
- func = svdm_rsp.identity;
- break;
- case CMD_DISCOVER_SVID:
- func = svdm_rsp.svids;
- break;
- case CMD_DISCOVER_MODES:
- func = svdm_rsp.modes;
- break;
- case CMD_ENTER_MODE:
- func = svdm_rsp.enter_mode;
- break;
- case CMD_DP_STATUS:
- if (svdm_rsp.amode)
- func = svdm_rsp.amode->status;
- break;
- case CMD_DP_CONFIG:
- if (svdm_rsp.amode)
- func = svdm_rsp.amode->config;
- break;
- case CMD_EXIT_MODE:
- func = svdm_rsp.exit_mode;
- break;
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- case CMD_ATTENTION:
- /*
- * attention is only SVDM with no response
- * (just goodCRC) return zero here.
- */
- dfp_consume_attention(port, payload);
- return 0;
-#endif
- default:
- CPRINTF("ERR:CMD:%d\n", cmd);
- rsize = 0;
- }
- if (func)
- rsize = func(port, payload);
- else /* not supported : NACK it */
- rsize = 0;
- if (rsize >= 1)
- payload[0] |= VDO_CMDT(CMDT_RSP_ACK);
- else if (!rsize) {
- payload[0] |= VDO_CMDT(CMDT_RSP_NAK);
- rsize = 1;
- } else {
- payload[0] |= VDO_CMDT(CMDT_RSP_BUSY);
- rsize = 1;
- }
- payload[0] |=
- VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP));
- } else if (cmd_type == CMDT_RSP_ACK) {
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- struct svdm_amode_data *modep;
-
- modep = pd_get_amode_data(port, TCPCI_MSG_SOP,
- PD_VDO_VID(payload[0]));
-#endif
- switch (cmd) {
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- case CMD_DISCOVER_IDENT:
- /* Received a SOP' Discover Ident msg */
- if (sop == TCPCI_MSG_SOP_PRIME) {
- rsize = process_am_discover_ident_sop_prime(
- port, cnt, head, payload);
- /* Received a SOP Discover Ident Message */
- } else {
- rsize = process_am_discover_ident_sop(
- port, cnt, head, payload, rtype);
- }
- break;
- case CMD_DISCOVER_SVID:
- rsize = process_am_discover_svids(port, cnt, payload,
- sop, rtype);
- break;
- case CMD_DISCOVER_MODES:
- dfp_consume_modes(port, sop, cnt, payload);
- if (is_tbt_compat_enabled(port) &&
- is_tbt_compat_mode(port, cnt, payload)) {
- rsize = process_tbt_compat_discover_modes(
- port, sop, payload, rtype);
- break;
- }
-
- rsize = dfp_discover_modes(port, payload);
- /* enter the default mode for DFP */
- if (!rsize) {
- /*
- * Disabling Thunderbolt-Compatible mode if
- * discover mode response doesn't include Intel
- * SVID.
- */
- disable_tbt_compat_mode(port);
- payload[0] = pd_dfp_enter_mode(
- port, TCPCI_MSG_SOP, 0, 0);
- if (payload[0])
- rsize = 1;
- }
- break;
- case CMD_ENTER_MODE:
- if (is_tbt_compat_enabled(port)) {
- rsize = obj_cnt_enter_tbt_compat_mode(
- port, sop, payload, rtype);
- /*
- * Continue with PD flow if
- * Thunderbolt-compatible mode is disabled.
- */
- } else if (!modep) {
- rsize = 0;
- } else {
- if (!modep->opos)
- pd_dfp_enter_mode(port, TCPCI_MSG_SOP,
- 0, 0);
-
- if (modep->opos) {
- rsize = modep->fx->status(port,
- payload);
- payload[0] |= PD_VDO_OPOS(modep->opos);
- }
- }
- break;
- case CMD_DP_STATUS:
- /* DP status response & UFP's DP attention have same
- payload */
- dfp_consume_attention(port, payload);
- if (modep && modep->opos)
- rsize = modep->fx->config(port, payload);
- else
- rsize = 0;
- break;
- case CMD_DP_CONFIG:
- if (modep && modep->opos && modep->fx->post_config)
- modep->fx->post_config(port);
- /* no response after DFPs ack */
- rsize = 0;
- break;
- case CMD_EXIT_MODE:
- /* no response after DFPs ack */
- rsize = 0;
- break;
-#endif
- case CMD_ATTENTION:
- /* no response after DFPs ack */
- rsize = 0;
- break;
- default:
- CPRINTF("ERR:CMD:%d\n", cmd);
- rsize = 0;
- }
-
- payload[0] |= VDO_CMDT(CMDT_INIT);
- payload[0] |=
- VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP));
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- } else if (cmd_type == CMDT_RSP_BUSY) {
- switch (cmd) {
- case CMD_DISCOVER_IDENT:
- case CMD_DISCOVER_SVID:
- case CMD_DISCOVER_MODES:
- /* resend if its discovery */
- rsize = 1;
- break;
- case CMD_ENTER_MODE:
- /* Error */
- CPRINTF("ERR:ENTBUSY\n");
- rsize = 0;
- break;
- case CMD_EXIT_MODE:
- rsize = 0;
- break;
- default:
- rsize = 0;
- }
- } else if (cmd_type == CMDT_RSP_NAK) {
- /* Passive cable Nacked for Discover SVID */
- if (cmd == CMD_DISCOVER_SVID && is_tbt_compat_enabled(port) &&
- sop == TCPCI_MSG_SOP_PRIME &&
- get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE) {
- limit_tbt_cable_speed(port);
- rsize = dfp_discover_modes(port, payload);
- } else {
- rsize = 0;
- }
-#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
- } else {
- CPRINTF("ERR:CMDT:%d\n", cmd);
- /* do not answer */
- rsize = 0;
- }
- return rsize;
-}
-
-#else
-
-int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload,
- uint32_t head, enum tcpci_msg_type *rtype)
-{
- return 0;
-}
-
-#endif /* CONFIG_USB_PD_ALT_MODE */
-
-#define FW_RW_END \
- (CONFIG_EC_WRITABLE_STORAGE_OFF + CONFIG_RW_STORAGE_OFF + \
- CONFIG_RW_SIZE)
-
-uint8_t *flash_hash_rw(void)
-{
- static struct sha256_ctx ctx;
-
- /* re-calculate RW hash when changed as its time consuming */
- if (rw_flash_changed) {
- rw_flash_changed = 0;
- SHA256_init(&ctx);
- SHA256_update(&ctx,
- (void *)CONFIG_PROGRAM_MEMORY_BASE +
- CONFIG_RW_MEM_OFF,
- CONFIG_RW_SIZE - RSANUMBYTES);
- return SHA256_final(&ctx);
- } else {
- return ctx.buf;
- }
-}
-
-void pd_get_info(uint32_t *info_data)
-{
- void *rw_hash = flash_hash_rw();
-
- /* copy first 20 bytes of RW hash */
- memcpy(info_data, rw_hash, 5 * sizeof(uint32_t));
- /* copy other info into data msg */
-#if defined(CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR) && \
- defined(CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR)
- info_data[5] = VDO_INFO(CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR,
- CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR,
- ver_get_num_commits(system_get_image_copy()),
- (system_get_image_copy() != EC_IMAGE_RO));
-#else
- info_data[5] = 0;
-#endif
-}
-
-int pd_custom_flash_vdm(int port, int cnt, uint32_t *payload)
-{
- static int flash_offset;
- int rsize = 1; /* default is just VDM header returned */
-
- switch (PD_VDO_CMD(payload[0])) {
- case VDO_CMD_VERSION:
- memcpy(payload + 1, &current_image_data.version, 24);
- rsize = 7;
- break;
- case VDO_CMD_REBOOT:
- /* ensure the power supply is in a safe state */
- pd_power_supply_reset(0);
- system_reset(0);
- break;
- case VDO_CMD_READ_INFO:
- /* copy info into response */
- pd_get_info(payload + 1);
- rsize = 7;
- break;
- case VDO_CMD_FLASH_ERASE:
- /* do not kill the code under our feet */
- if (system_get_image_copy() != EC_IMAGE_RO)
- break;
- pd_log_event(PD_EVENT_ACC_RW_ERASE, 0, 0, NULL);
- flash_offset =
- CONFIG_EC_WRITABLE_STORAGE_OFF + CONFIG_RW_STORAGE_OFF;
- crec_flash_physical_erase(CONFIG_EC_WRITABLE_STORAGE_OFF +
- CONFIG_RW_STORAGE_OFF,
- CONFIG_RW_SIZE);
- rw_flash_changed = 1;
- break;
- case VDO_CMD_FLASH_WRITE:
- /* do not kill the code under our feet */
- if ((system_get_image_copy() != EC_IMAGE_RO) ||
- (flash_offset <
- CONFIG_EC_WRITABLE_STORAGE_OFF + CONFIG_RW_STORAGE_OFF))
- break;
- crec_flash_physical_write(flash_offset, 4 * (cnt - 1),
- (const char *)(payload + 1));
- flash_offset += 4 * (cnt - 1);
- rw_flash_changed = 1;
- break;
- case VDO_CMD_ERASE_SIG:
- /* this is not touching the code area */
- {
- uint32_t zero = 0;
- int offset;
- /* zeroes the area containing the RSA signature */
- for (offset = FW_RW_END - RSANUMBYTES;
- offset < FW_RW_END; offset += 4)
- crec_flash_physical_write(offset, 4,
- (const char *)&zero);
- }
- break;
- default:
- /* Unknown : do not answer */
- return 0;
- }
- return rsize;
-}
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
deleted file mode 100644
index abf75e8004..0000000000
--- a/common/usb_pd_protocol.c
+++ /dev/null
@@ -1,5449 +0,0 @@
-/* Copyright 2014 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.
- */
-
-#include "atomic.h"
-#include "battery.h"
-#include "battery_smart.h"
-#include "board.h"
-#include "charge_manager.h"
-#include "charge_state.h"
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "cros_version.h"
-#include "ec_commands.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "printf.h"
-#include "registers.h"
-#include "system.h"
-#include "task.h"
-#include "tcpm/tcpci.h"
-#include "tcpm/tcpm.h"
-#include "timer.h"
-#include "util.h"
-#include "usb_charge.h"
-#include "usb_common.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "usb_pd_flags.h"
-#include "usb_pd_tcpm.h"
-#include "usb_pd_tcpc.h"
-#include "usbc_ocp.h"
-#include "usbc_ppc.h"
-#include "vboot.h"
-
-/* Flags to clear on a disconnect */
-#define PD_FLAGS_RESET_ON_DISCONNECT_MASK (PD_FLAGS_PARTNER_DR_POWER | \
- PD_FLAGS_PARTNER_DR_DATA | \
- PD_FLAGS_CHECK_IDENTITY | \
- PD_FLAGS_SNK_CAP_RECVD | \
- PD_FLAGS_TCPC_DRP_TOGGLE | \
- PD_FLAGS_EXPLICIT_CONTRACT | \
- PD_FLAGS_PREVIOUS_PD_CONN | \
- PD_FLAGS_CHECK_PR_ROLE | \
- PD_FLAGS_CHECK_DR_ROLE | \
- PD_FLAGS_PARTNER_UNCONSTR | \
- PD_FLAGS_VCONN_ON | \
- PD_FLAGS_TRY_SRC | \
- PD_FLAGS_PARTNER_USB_COMM | \
- PD_FLAGS_UPDATE_SRC_CAPS | \
- PD_FLAGS_TS_DTS_PARTNER | \
- PD_FLAGS_SNK_WAITING_BATT | \
- PD_FLAGS_CHECK_VCONN_STATE)
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-
-static int tcpc_prints(const char *string, int port)
-{
- return CPRINTS("TCPC p%d %s", port, string);
-}
-
-BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT <= EC_USB_PD_MAX_PORTS);
-
-/*
- * Debug log level - higher number == more log
- * Level 0: Log state transitions
- * Level 1: Level 0, plus state name
- * Level 2: Level 1, plus packet info
- * Level 3: Level 2, plus ping packet and packet dump on error
- *
- * Note that higher log level causes timing changes and thus may affect
- * performance.
- *
- * Can be limited to constant debug_level by CONFIG_USB_PD_DEBUG_LEVEL
- */
-#ifdef CONFIG_USB_PD_DEBUG_LEVEL
-static const int debug_level = CONFIG_USB_PD_DEBUG_LEVEL;
-#else
-static int debug_level;
-#endif
-
-/*
- * PD communication enabled flag. When false, PD state machine still
- * detects source/sink connection and disconnection, and will still
- * provide VBUS, but never sends any PD communication.
- */
-static uint8_t pd_comm_enabled[CONFIG_USB_PD_PORT_MAX_COUNT];
-#else /* CONFIG_COMMON_RUNTIME */
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#define tcpc_prints(string, port)
-static const int debug_level;
-#endif
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-#define DUAL_ROLE_IF_ELSE(port, sink_clause, src_clause) \
- (pd[port].power_role == PD_ROLE_SINK ? (sink_clause) : (src_clause))
-#else
-#define DUAL_ROLE_IF_ELSE(port, sink_clause, src_clause) (src_clause)
-#endif
-
-#define READY_RETURN_STATE(port) DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_READY, \
- PD_STATE_SRC_READY)
-
-/* Type C supply voltage (mV) */
-#define TYPE_C_VOLTAGE 5000 /* mV */
-
-/* PD counter definitions */
-#define PD_MESSAGE_ID_COUNT 7
-#define PD_HARD_RESET_COUNT 2
-#define PD_CAPS_COUNT 50
-#define PD_SNK_CAP_RETRIES 3
-
-/*
- * The time that we allow the port partner to send any messages after an
- * explicit contract is established. 200ms was chosen somewhat arbitrarily as
- * it should be long enough for sources to decide to send a message if they were
- * going to, but not so long that a "low power charger connected" notification
- * would be shown in the chrome OS UI.
- */
-#define SNK_READY_HOLD_OFF_US (200 * MSEC)
-/*
- * For the same purpose as SNK_READY_HOLD_OFF_US, but this delay can be longer
- * since the concern over "low power charger" is not relevant when connected as
- * a source and the additional delay avoids a race condition where the partner
- * port sends a power role swap request close to when the VDM discover identity
- * message gets sent.
- */
-#define SRC_READY_HOLD_OFF_US (400 * MSEC)
-
-enum ams_seq {
- AMS_START,
- AMS_RESPONSE,
-};
-
-enum vdm_states {
- VDM_STATE_ERR_BUSY = -3,
- VDM_STATE_ERR_SEND = -2,
- VDM_STATE_ERR_TMOUT = -1,
- VDM_STATE_DONE = 0,
- /* Anything >0 represents an active state */
- VDM_STATE_READY = 1,
- VDM_STATE_BUSY = 2,
- VDM_STATE_WAIT_RSP_BUSY = 3,
-};
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-/* Port dual-role state */
-enum pd_dual_role_states drp_state[CONFIG_USB_PD_PORT_MAX_COUNT] = {
- [0 ... (CONFIG_USB_PD_PORT_MAX_COUNT - 1)] =
- CONFIG_USB_PD_INITIAL_DRP_STATE};
-
-/* Enable variable for Try.SRC states */
-static bool pd_try_src_enable;
-#endif
-
-#ifdef CONFIG_USB_PD_REV30
-/*
- * The spec. revision is the argument for this macro.
- * Rev 0 (PD 1.0) - return PD_CTRL_REJECT
- * Rev 1 (PD 2.0) - return PD_CTRL_REJECT
- * Rev 2 (PD 3.0) - return PD_CTRL_NOT_SUPPORTED
- *
- * Note: this should only be used in locations where responding on a lower
- * revision with a Reject is valid (ex. a source refusing a PR_Swap). For
- * other uses of Not_Supported, use PD_CTRL_NOT_SUPPORTED directly.
- */
-#define NOT_SUPPORTED(r) (r < 2 ? PD_CTRL_REJECT : PD_CTRL_NOT_SUPPORTED)
-#else
-#define NOT_SUPPORTED(r) PD_CTRL_REJECT
-#endif
-
-#ifdef CONFIG_USB_PD_REV30
-/*
- * The spec. revision is used to index into this array.
- * Rev 0 (VDO 1.0) - return VDM_VER10
- * Rev 1 (VDO 1.0) - return VDM_VER10
- * Rev 2 (VDO 2.0) - return VDM_VER20
- */
-static const uint8_t vdo_ver[] = {
- VDM_VER10, VDM_VER10, VDM_VER20};
-#define VDO_VER(v) vdo_ver[v]
-#else
-#define VDO_VER(v) VDM_VER10
-#endif
-
-static struct pd_protocol {
- /* current port power role (SOURCE or SINK) */
- enum pd_power_role power_role;
- /* current port data role (DFP or UFP) */
- enum pd_data_role data_role;
- /* 3-bit rolling message ID counter */
- uint8_t msg_id;
- /* port polarity */
- enum tcpc_cc_polarity polarity;
- /* PD state for port */
- enum pd_states task_state;
- /* PD state when we run state handler the last time */
- enum pd_states last_state;
- /* bool: request state change to SUSPENDED */
- uint8_t req_suspend_state;
- /* The state to go to after timeout */
- enum pd_states timeout_state;
- /* port flags, see PD_FLAGS_* */
- uint32_t flags;
- /* Timeout for the current state. Set to 0 for no timeout. */
- uint64_t timeout;
- /* Time for source recovery after hard reset */
- uint64_t src_recover;
- /* Time for CC debounce end */
- uint64_t cc_debounce;
- /* The cc state */
- enum pd_cc_states cc_state;
- /* status of last transmit */
- uint8_t tx_status;
-
- /* Last received */
- uint8_t last_msg_id;
-
- /* last requested voltage PDO index */
- int requested_idx;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /* Current limit / voltage based on the last request message */
- uint32_t curr_limit;
- uint32_t supply_voltage;
- /* Signal charging update that affects the port */
- int new_power_request;
- /* Store previously requested voltage request */
- int prev_request_mv;
- /* Time for Try.SRC states */
- uint64_t try_src_marker;
- uint64_t try_timeout;
-#endif
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /* Time to enter low power mode */
- uint64_t low_power_time;
- /* 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;
- /* Tasks preventing TCPC from entering low power mode */
- int tasks_preventing_lpm;
-#endif
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- /*
- * Timer for handling TOGGLE_OFF/FORCE_SINK mode when auto-toggle
- * enabled. See drp_auto_toggle_next_state() for details.
- */
- uint64_t drp_sink_time;
-#endif
-
- /*
- * Time to ignore Vbus absence due to external IC debounce detection
- * logic immediately after a power role swap.
- */
- uint64_t vbus_debounce_time;
-
- /* PD state for Vendor Defined Messages */
- enum vdm_states vdm_state;
- /* Timeout for the current vdm state. Set to 0 for no timeout. */
- timestamp_t vdm_timeout;
- /* next Vendor Defined Message to send */
- uint32_t vdo_data[VDO_MAX_SIZE];
- /* type of transmit message (SOP/SOP'/SOP'') */
- enum tcpci_msg_type xmit_type;
- uint8_t vdo_count;
- /* VDO to retry if UFP responder replied busy. */
- uint32_t vdo_retry;
-
- /* Attached ChromeOS device id, RW hash, and current RO / RW image */
- uint16_t dev_id;
- uint32_t dev_rw_hash[PD_RW_HASH_SIZE/4];
- enum ec_image current_image;
-#ifdef CONFIG_USB_PD_REV30
- /* protocol revision */
- uint8_t rev;
-#endif
- /*
- * Some port partners are really chatty after an explicit contract is
- * established. Therefore, we allow this time for the port partner to
- * send any messages in order to avoid a collision of sending messages
- * of our own.
- */
- uint64_t ready_state_holdoff_timer;
- /*
- * PD 2.0 spec, section 6.5.11.1
- * When we can give up on a HARD_RESET transmission.
- */
- uint64_t hard_reset_complete_timer;
-} pd[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-#ifdef CONFIG_USB_PD_TCPMV1_DEBUG
-static const char * const pd_state_names[] = {
- "DISABLED", "SUSPENDED",
- "SNK_DISCONNECTED", "SNK_DISCONNECTED_DEBOUNCE",
- "SNK_HARD_RESET_RECOVER",
- "SNK_DISCOVERY", "SNK_REQUESTED", "SNK_TRANSITION", "SNK_READY",
- "SNK_SWAP_INIT", "SNK_SWAP_SNK_DISABLE",
- "SNK_SWAP_SRC_DISABLE", "SNK_SWAP_STANDBY", "SNK_SWAP_COMPLETE",
- "SRC_DISCONNECTED", "SRC_DISCONNECTED_DEBOUNCE",
- "SRC_HARD_RESET_RECOVER", "SRC_STARTUP",
- "SRC_DISCOVERY", "SRC_NEGOCIATE", "SRC_ACCEPTED", "SRC_POWERED",
- "SRC_TRANSITION", "SRC_READY", "SRC_GET_SNK_CAP", "DR_SWAP",
- "SRC_SWAP_INIT", "SRC_SWAP_SNK_DISABLE", "SRC_SWAP_SRC_DISABLE",
- "SRC_SWAP_STANDBY",
- "VCONN_SWAP_SEND", "VCONN_SWAP_INIT", "VCONN_SWAP_READY",
- "SOFT_RESET", "HARD_RESET_SEND", "HARD_RESET_EXECUTE", "BIST_RX",
- "BIST_TX",
- "DRP_AUTO_TOGGLE",
- "ENTER_USB",
-};
-BUILD_ASSERT(ARRAY_SIZE(pd_state_names) == PD_STATE_COUNT);
-#endif
-
-int pd_comm_is_enabled(int port)
-{
-#ifdef CONFIG_COMMON_RUNTIME
- return pd_comm_enabled[port];
-#else
- return 1;
-#endif
-}
-
-bool pd_alt_mode_capable(int port)
-{
- /*
- * PD is alternate mode capable only if PD communication is enabled and
- * the port is not suspended.
- */
- return pd_comm_is_enabled(port) &&
- !(pd[port].task_state == PD_STATE_SUSPENDED);
-}
-
-static inline void set_state_timeout(int port,
- uint64_t timeout,
- enum pd_states timeout_state)
-{
- pd[port].timeout = timeout;
- pd[port].timeout_state = timeout_state;
-}
-
-int pd_get_rev(int port, enum tcpci_msg_type type)
-{
-#ifdef CONFIG_USB_PD_REV30
- /* TCPMv1 Only stores PD revision for SOP and SOP' types */
- ASSERT(type < NUM_SOP_STAR_TYPES - 1);
-
- if (type == TCPCI_MSG_SOP_PRIME)
- return get_usb_pd_cable_revision(port);
-
- return pd[port].rev;
-#else
- return PD_REV20;
-#endif
-}
-
-int pd_get_vdo_ver(int port, enum tcpci_msg_type type)
-{
-#ifdef CONFIG_USB_PD_REV30
- if (type == TCPCI_MSG_SOP_PRIME)
- return vdo_ver[get_usb_pd_cable_revision(port)];
-
- return vdo_ver[pd[port].rev];
-#else
- return VDM_VER10;
-#endif
-}
-
-/* Return flag for pd state is connected */
-int pd_is_connected(int port)
-{
- if (pd[port].task_state == PD_STATE_DISABLED)
- return 0;
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- if (pd[port].task_state == PD_STATE_DRP_AUTO_TOGGLE)
- return 0;
-#endif
-
- return DUAL_ROLE_IF_ELSE(port,
- /* sink */
- pd[port].task_state != PD_STATE_SNK_DISCONNECTED &&
- pd[port].task_state != PD_STATE_SNK_DISCONNECTED_DEBOUNCE,
- /* source */
- pd[port].task_state != PD_STATE_SRC_DISCONNECTED &&
- pd[port].task_state != PD_STATE_SRC_DISCONNECTED_DEBOUNCE);
-}
-
-/* Return true if partner port is known to be PD capable. */
-bool pd_capable(int port)
-{
- return !!(pd[port].flags & PD_FLAGS_PREVIOUS_PD_CONN);
-}
-
-/*
- * For TCPMv1, this routine always returns false so that the USB3 signals
- * are connected without delay when the initial connection is UFP.
- */
-bool pd_waiting_on_partner_src_caps(int port)
-{
- return false;
-}
-
-/*
- * Return true if partner port is capable of communication over USB data
- * lines.
- */
-bool pd_get_partner_usb_comm_capable(int port)
-{
- return !!(pd[port].flags & PD_FLAGS_PARTNER_USB_COMM);
-}
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-void pd_vbus_low(int port)
-{
- pd[port].flags &= ~PD_FLAGS_VBUS_NEVER_LOW;
-}
-#endif
-
-
-#ifdef CONFIG_USBC_VCONN
-static void set_vconn(int port, int enable)
-{
- /*
- * Disable PPC Vconn first then TCPC in case the voltage feeds back
- * to TCPC and damages.
- */
- if (IS_ENABLED(CONFIG_USBC_PPC_VCONN) && !enable)
- ppc_set_vconn(port, 0);
-
- /*
- * Some TCPCs/PPC combinations can trigger OVP if the TCPC doesn't
- * source VCONN. This happens if the TCPC will trip OVP with 5V, and the
- * PPC doesn't isolate the TCPC from VCONN when sourcing. But, some PPCs
- * which do isolate the TCPC can't handle 5V on its host-side CC pins,
- * so the TCPC shouldn't source VCONN in those cases.
- *
- * In the first case, both TCPC and PPC will potentially source Vconn,
- * but that should be okay since Vconn has "make before break"
- * electrical requirements when swapping anyway.
- *
- * See b/72961003 and b/180973460
- */
- tcpm_set_vconn(port, enable);
-
- if (IS_ENABLED(CONFIG_USBC_PPC_VCONN) && enable)
- ppc_set_vconn(port, 1);
-}
-#endif /* defined(CONFIG_USBC_VCONN) */
-
-#ifdef CONFIG_USB_PD_REV30
-/* Note: rp should be set to either SINK_TX_OK or SINK_TX_NG */
-static void sink_can_xmit(int port, int rp)
-{
- tcpm_select_rp_value(port, rp);
- tcpm_set_cc(port, TYPEC_CC_RP);
-
- /* We must wait tSinkTx before sending a message */
- if (rp == SINK_TX_NG)
- usleep(PD_T_SINK_TX);
-}
-#endif
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
-
-/* 10 ms is enough time for any TCPC transaction to complete. */
-#define PD_LPM_DEBOUNCE_US (10 * MSEC)
-/* 25 ms on LPM exit to ensure TCPC is settled */
-#define PD_LPM_EXIT_DEBOUNCE_US (25 * MSEC)
-
-/* This is only called from the PD tasks that owns the port. */
-static void handle_device_access(int port)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- pd[port].low_power_time = get_time().val + PD_LPM_DEBOUNCE_US;
- if (pd[port].flags & PD_FLAGS_LPM_ENGAGED) {
- tcpc_prints("Exit Low Power Mode", port);
- pd[port].flags &= ~(PD_FLAGS_LPM_ENGAGED |
- PD_FLAGS_LPM_REQUESTED);
- pd[port].flags |= PD_FLAGS_LPM_EXIT;
-
- pd[port].low_power_exit_time = get_time().val
- + PD_LPM_EXIT_DEBOUNCE_US;
- /*
- * Wake to ensure we make another pass through the main task
- * loop after clearing the flags.
- */
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-static int pd_device_in_low_power(int port)
-{
- /*
- * If we are actively waking the device up in the PD task, do not
- * let TCPC operation wait or retry because we are in low power mode.
- */
- if (port == TASK_ID_TO_PD_PORT(task_get_current()) &&
- (pd[port].flags & PD_FLAGS_LPM_TRANSITION))
- return 0;
-
- return pd[port].flags & PD_FLAGS_LPM_ENGAGED;
-}
-
-static int reset_device_and_notify(int port)
-{
- int rv;
- int task, waiting_tasks;
-
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- pd[port].flags |= PD_FLAGS_LPM_TRANSITION;
- rv = tcpm_init(port);
- pd[port].flags &= ~PD_FLAGS_LPM_TRANSITION;
-
- if (rv == EC_SUCCESS)
- tcpc_prints("init ready", port);
- else
- tcpc_prints("init failed!", port);
-
- /*
- * Before getting the other tasks that are waiting, clear the reset
- * event from this PD task to prevent multiple reset/init events
- * occurring.
- *
- * The double reset event happens when the higher priority PD interrupt
- * task gets an interrupt during the above tcpm_init function. When that
- * occurs, the higher priority task waits correctly for us to finish
- * waking the TCPC, but it has also set PD_EVENT_TCPC_RESET again, which
- * would result in a second, unnecessary init.
- */
- atomic_clear_bits(task_get_event_bitmap(task_get_current()),
- PD_EVENT_TCPC_RESET);
-
- waiting_tasks = atomic_clear(&pd[port].tasks_waiting_on_reset);
-
- /*
- * Now that we are done waking up the device, handle device access
- * manually because we ignored it while waking up device.
- */
- handle_device_access(port);
-
- /* Clear SW LPM state; the state machine will set it again if needed */
- pd[port].flags &= ~PD_FLAGS_LPM_REQUESTED;
-
- /* Wake up all waiting tasks. */
- while (waiting_tasks) {
- task = __fls(waiting_tasks);
- waiting_tasks &= ~BIT(task);
- task_set_event(task, TASK_EVENT_PD_AWAKE);
- }
-
- return rv;
-}
-
-static void pd_wait_for_wakeup(int port)
-{
- if (port == TASK_ID_TO_PD_PORT(task_get_current())) {
- /* If we are in the PD task, we can directly reset */
- reset_device_and_notify(port);
- } else {
- /* Otherwise, we need to wait for the TCPC reset to complete */
- atomic_or(&pd[port].tasks_waiting_on_reset,
- 1 << task_get_current());
- /*
- * NOTE: We could be sending the PD task the reset event while
- * it is already processing the reset event. If that occurs,
- * then we will reset the TCPC multiple times, which is
- * undesirable but most likely benign. Empirically, this doesn't
- * happen much, but it if starts occurring, we can add a guard
- * to prevent/reduce it.
- */
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TCPC_RESET);
- task_wait_event_mask(TASK_EVENT_PD_AWAKE, -1);
- }
-}
-
-void pd_wait_exit_low_power(int port)
-{
- if (pd_device_in_low_power(port))
- pd_wait_for_wakeup(port);
-}
-
-/*
- * This can be called from any task. If we are in the PD task, we can handle
- * immediately. Otherwise, we need to notify the PD task via event.
- */
-void pd_device_accessed(int port)
-{
- if (port == TASK_ID_TO_PD_PORT(task_get_current())) {
- /* Ignore any access to device while it is waking up */
- if (pd[port].flags & PD_FLAGS_LPM_TRANSITION)
- return;
-
- handle_device_access(port);
- } else {
- task_set_event(PD_PORT_TO_TASK_ID(port),
- PD_EVENT_DEVICE_ACCESSED);
- }
-}
-
-void pd_prevent_low_power_mode(int port, int prevent)
-{
- const int current_task_mask = (1 << task_get_current());
-
- if (prevent)
- atomic_or(&pd[port].tasks_preventing_lpm, current_task_mask);
- else
- atomic_clear_bits(&pd[port].tasks_preventing_lpm,
- current_task_mask);
-}
-
-/* This is only called from the PD tasks that owns the port. */
-static void exit_low_power_mode(int port)
-{
- if (pd[port].flags & PD_FLAGS_LPM_ENGAGED)
- reset_device_and_notify(port);
- else
- pd[port].flags &= ~PD_FLAGS_LPM_REQUESTED;
-}
-
-#else /* !CONFIG_USB_PD_TCPC_LOW_POWER */
-
-/* We don't need to notify anyone if low power mode isn't involved. */
-static int reset_device_and_notify(int port)
-{
- const int rv = tcpm_init(port);
-
- if (rv == EC_SUCCESS)
- tcpc_prints("init ready", port);
- else
- tcpc_prints("init failed!", port);
-
- return rv;
-}
-
-#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */
-
-/**
- * Invalidate last message received at the port when the port gets disconnected
- * or reset(soft/hard). This is used to identify and handle the duplicate
- * messages.
- *
- * @param port USB PD TCPC port number
- */
-static void invalidate_last_message_id(int port)
-{
- pd[port].last_msg_id = INVALID_MSG_ID_COUNTER;
-}
-
-static bool consume_sop_repeat_message(int port, uint8_t msg_id)
-{
- if (pd[port].last_msg_id != msg_id) {
- pd[port].last_msg_id = msg_id;
- return false;
- }
- CPRINTF("C%d Repeat msg_id %d\n", port, msg_id);
- return true;
-}
-
-/**
- * Identify and drop any duplicate messages received at the port.
- *
- * @param port USB PD TCPC port number
- * @param msg_header Message Header containing the RX message ID
- * @return True if the received message is a duplicate one, False otherwise.
- *
- * From USB PD version 1.3 section 6.7.1, the port which communicates
- * using SOP* Packets Shall maintain copies of the last MessageID for
- * each type of SOP* it uses.
- */
-static bool consume_repeat_message(int port, uint32_t msg_header)
-{
- uint8_t msg_id = PD_HEADER_ID(msg_header);
- enum tcpci_msg_type sop = PD_HEADER_GET_SOP(msg_header);
-
- /* If repeat message ignore, except softreset control request. */
- if (PD_HEADER_TYPE(msg_header) == PD_CTRL_SOFT_RESET &&
- PD_HEADER_CNT(msg_header) == 0) {
- return false;
- } else if (sop == TCPCI_MSG_SOP_PRIME) {
- return consume_sop_prime_repeat_msg(port, msg_id);
- } else if (sop == TCPCI_MSG_SOP_PRIME_PRIME) {
- return consume_sop_prime_prime_repeat_msg(port, msg_id);
- } else {
- return consume_sop_repeat_message(port, msg_id);
- }
-
-}
-
-/**
- * Returns true if the port is currently in the try src state.
- */
-static inline int is_try_src(int port)
-{
- return pd[port].flags & PD_FLAGS_TRY_SRC;
-}
-
-static inline void set_state(int port, enum pd_states next_state)
-{
- enum pd_states last_state = pd[port].task_state;
-#if defined(CONFIG_LOW_POWER_IDLE) && !defined(CONFIG_USB_PD_TCPC_ON_CHIP)
- int i;
-#endif
- int not_auto_toggling = 1;
-
- set_state_timeout(port, 0, 0);
- pd[port].task_state = next_state;
-
- if (last_state == next_state)
- return;
-
-#if defined(CONFIG_USBC_PPC) && defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE)
- /* If we're entering DRP_AUTO_TOGGLE, there is no sink connected. */
- if (next_state == PD_STATE_DRP_AUTO_TOGGLE) {
- ppc_dev_is_connected(port, PPC_DEV_DISCONNECTED);
- /* Disable Auto Discharge Disconnect */
- tcpm_enable_auto_discharge_disconnect(port, 0);
-
- if (IS_ENABLED(CONFIG_USBC_OCP)) {
- usbc_ocp_snk_is_connected(port, false);
- /*
- * Clear the overcurrent event counter
- * since we've detected a disconnect.
- */
- usbc_ocp_clear_event_counter(port);
- }
- }
-#endif /* CONFIG_USBC_PPC && CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE */
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- if (last_state != PD_STATE_DRP_AUTO_TOGGLE)
- /* Clear flag to allow DRP auto toggle when possible */
- pd[port].flags &= ~PD_FLAGS_TCPC_DRP_TOGGLE;
- else
- /* This is an auto toggle instead of disconnect */
- not_auto_toggling = 0;
-#endif
-
- /* Ignore dual-role toggling between sink and source */
- if ((last_state == PD_STATE_SNK_DISCONNECTED &&
- next_state == PD_STATE_SRC_DISCONNECTED) ||
- (last_state == PD_STATE_SRC_DISCONNECTED &&
- next_state == PD_STATE_SNK_DISCONNECTED))
- return;
-
- if (next_state == PD_STATE_SRC_DISCONNECTED ||
- next_state == PD_STATE_SNK_DISCONNECTED) {
-#ifdef CONFIG_USBC_PPC
- enum tcpc_cc_voltage_status cc1, cc2;
-
- tcpm_get_cc(port, &cc1, &cc2);
- /*
- * Neither a debug accessory nor UFP attached.
- * Tell the PPC module that there is no device connected.
- */
- if (!cc_is_at_least_one_rd(cc1, cc2)) {
- ppc_dev_is_connected(port, PPC_DEV_DISCONNECTED);
-
- if (IS_ENABLED(CONFIG_USBC_OCP)) {
- usbc_ocp_snk_is_connected(port, false);
- /*
- * Clear the overcurrent event counter
- * since we've detected a disconnect.
- */
- usbc_ocp_clear_event_counter(port);
- }
- }
-#endif /* CONFIG_USBC_PPC */
-
- /* Clear the holdoff timer since the port is disconnected. */
- pd[port].ready_state_holdoff_timer = 0;
-
- /*
- * We should not clear any flags when transitioning back to the
- * disconnected state from the debounce state as the two states
- * here are really the same states in the state diagram.
- */
- if (last_state != PD_STATE_SNK_DISCONNECTED_DEBOUNCE &&
- last_state != PD_STATE_SRC_DISCONNECTED_DEBOUNCE) {
- pd[port].flags &= ~PD_FLAGS_RESET_ON_DISCONNECT_MASK;
- reset_pd_cable(port);
- }
-
- /* Clear the input current limit */
- pd_set_input_current_limit(port, 0, 0);
-#ifdef CONFIG_CHARGE_MANAGER
- typec_set_input_current_limit(port, 0, 0);
- charge_manager_set_ceil(port,
- CEIL_REQUESTOR_PD,
- CHARGE_CEIL_NONE);
-#endif
-#ifdef CONFIG_BC12_DETECT_DATA_ROLE_TRIGGER
- /*
- * When data role set events are used to enable BC1.2, then CC
- * detach events are used to notify BC1.2 that it can be powered
- * down.
- */
- task_set_event(USB_CHG_PORT_TO_TASK_ID(port),
- USB_CHG_EVENT_CC_OPEN);
-#endif /* CONFIG_BC12_DETECT_DATA_ROLE_TRIGGER */
-#ifdef CONFIG_USBC_VCONN
- set_vconn(port, 0);
-#endif /* defined(CONFIG_USBC_VCONN) */
- pd_update_saved_port_flags(port, PD_BBRMFLG_EXPLICIT_CONTRACT,
- 0);
-#else /* CONFIG_USB_PD_DUAL_ROLE */
- if (next_state == PD_STATE_SRC_DISCONNECTED) {
-#ifdef CONFIG_USBC_VCONN
- set_vconn(port, 0);
-#endif /* CONFIG_USBC_VCONN */
-#endif /* !CONFIG_USB_PD_DUAL_ROLE */
- /* If we are source, make sure VBUS is off and restore RP */
- if (pd[port].power_role == PD_ROLE_SOURCE) {
- /* Restore non-active ports to CONFIG_USB_PD_PULLUP */
- pd_power_supply_reset(port);
- tcpm_set_cc(port, TYPEC_CC_RP);
- }
-#ifdef CONFIG_USB_PD_REV30
- /* Adjust rev to highest level*/
- pd[port].rev = PD_REV30;
-#endif
- pd[port].dev_id = 0;
-#ifdef CONFIG_CHARGE_MANAGER
- charge_manager_update_dualrole(port, CAP_UNKNOWN);
-#endif
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- if (pd_dfp_exit_mode(port, TCPCI_MSG_SOP, 0, 0))
- usb_mux_set_safe_mode(port);
-#endif
- /*
- * Indicate that the port is disconnected by setting role to
- * DFP as SoCs have special signals when they are the UFP ports
- * (e.g. OTG signals)
- */
- pd_execute_data_swap(port, PD_ROLE_DFP);
-#ifdef CONFIG_USBC_SS_MUX
- usb_mux_set(port, USB_PD_MUX_NONE, USB_SWITCH_DISCONNECT,
- pd[port].polarity);
-#endif
- /* Disable TCPC RX */
- tcpm_set_rx_enable(port, 0);
-
- /* Invalidate message IDs. */
- invalidate_last_message_id(port);
-
- if (not_auto_toggling)
- /* Disable Auto Discharge Disconnect */
- tcpm_enable_auto_discharge_disconnect(port, 0);
-
- /* detect USB PD cc disconnect */
- if (IS_ENABLED(CONFIG_COMMON_RUNTIME))
- hook_notify(HOOK_USB_PD_DISCONNECT);
- }
-
-#ifdef CONFIG_USB_PD_REV30
- /* Upon entering SRC_READY, it is safe for the sink to transmit */
- if (next_state == PD_STATE_SRC_READY) {
- if (pd[port].rev == PD_REV30 &&
- pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT)
- sink_can_xmit(port, SINK_TX_OK);
- }
-#endif
-
-#if defined(CONFIG_LOW_POWER_IDLE) && !defined(CONFIG_USB_PD_TCPC_ON_CHIP)
- /* If a PD device is attached then disable deep sleep */
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- if (pd_capable(i))
- break;
- }
- if (i == board_get_usb_pd_port_count())
- enable_sleep(SLEEP_MASK_USB_PD);
- else
- disable_sleep(SLEEP_MASK_USB_PD);
-#endif
-
-#ifdef CONFIG_USB_PD_TCPMV1_DEBUG
- if (debug_level > 0)
- CPRINTF("C%d st%d %s\n", port, next_state,
- pd_state_names[next_state]);
- else
-#endif
- CPRINTF("C%d st%d\n", port, next_state);
-}
-
-/* increment message ID counter */
-static void inc_id(int port)
-{
- pd[port].msg_id = (pd[port].msg_id + 1) & PD_MESSAGE_ID_COUNT;
-}
-
-void pd_transmit_complete(int port, int status)
-{
- if (status == TCPC_TX_COMPLETE_SUCCESS)
- inc_id(port);
-
- pd[port].tx_status = status;
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TX);
-}
-
-static int pd_transmit(int port, enum tcpci_msg_type type,
- uint16_t header, const uint32_t *data, enum ams_seq ams)
-{
- int evt;
- int res;
-#ifdef CONFIG_USB_PD_REV30
- int sink_ng = 0;
-#endif
-
- /* If comms are disabled, do not transmit, return error */
- if (!pd_comm_is_enabled(port))
- return -1;
-
- /* Don't try to transmit anything until we have processed
- * all RX messages.
- */
- if (tcpm_has_pending_message(port))
- return -1;
-
-#ifdef CONFIG_USB_PD_REV30
- /* Source-coordinated collision avoidance */
- /*
- * USB PD Rev 3.0, Version 2.0: Section 2.7.3.2
- * Collision Avoidance - Protocol Layer
- *
- * In order to avoid message collisions due to asynchronous Messaging
- * sent from the Sink, the Source sets Rp to SinkTxOk (3A) to indicate
- * to the Sink that it is ok to initiate an AMS. When the Source wishes
- * to initiate an AMS, it sets Rp to SinkTxNG (1.5A).
- * When the Sink detects that Rp is set to SinkTxOk, it May initiate an
- * AMS. When the Sink detects that Rp is set to SinkTxNG it Shall Not
- * initiate an AMS and Shall only send Messages that are part of an AMS
- * the Source has initiated.
- * Note that this restriction applies to SOP* AMS’s i.e. for both Port
- * to Port and Port to Cable Plug communications.
- *
- * This starts after an Explicit Contract is in place (see section 2.5.2
- * SOP* Collision Avoidance).
- *
- * Note: a Sink can still send Hard Reset signaling at any time.
- */
- if ((pd[port].rev == PD_REV30) && ams == AMS_START &&
- (pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT)) {
- if (pd[port].power_role == PD_ROLE_SOURCE) {
- /*
- * Inform Sink that it can't transmit. If a sink
- * transmission is in progress and a collision occurs,
- * a reset is generated. This should be rare because
- * all extended messages are chunked. This effectively
- * defaults to PD REV 2.0 collision avoidance.
- */
- sink_can_xmit(port, SINK_TX_NG);
- sink_ng = 1;
- } else if (type != TCPCI_MSG_TX_HARD_RESET) {
- enum tcpc_cc_voltage_status cc1, cc2;
-
- tcpm_get_cc(port, &cc1, &cc2);
- if (cc1 == TYPEC_CC_VOLT_RP_1_5 ||
- cc2 == TYPEC_CC_VOLT_RP_1_5) {
- /* Sink can't transmit now. */
- /* Return failure, pd_task can retry later */
- return -1;
- }
- }
- }
-#endif
- tcpm_transmit(port, type, header, data);
-
- /* Wait until TX is complete */
- evt = task_wait_event_mask(PD_EVENT_TX, PD_T_TCPC_TX_TIMEOUT);
-
- if (evt & TASK_EVENT_TIMER)
- return -1;
-
- /* TODO: give different error condition for failed vs discarded */
- res = pd[port].tx_status == TCPC_TX_COMPLETE_SUCCESS ? 1 : -1;
-
-#ifdef CONFIG_USB_PD_REV30
- /* If the AMS transaction failed to start, reset CC to OK */
- if (res < 0 && sink_ng)
- sink_can_xmit(port, SINK_TX_OK);
-#endif
- return res;
-}
-
-static void pd_update_roles(int port)
-{
- /* Notify TCPC of role update */
- tcpm_set_msg_header(port, pd[port].power_role, pd[port].data_role);
-}
-
-static int send_control(int port, int type)
-{
- int bit_len;
- uint16_t header = PD_HEADER(type, pd[port].power_role,
- pd[port].data_role, pd[port].msg_id, 0,
- pd_get_rev(port, TCPCI_MSG_SOP), 0);
- /*
- * For PD 3.0, collision avoidance logic needs to know if this message
- * will begin a new Atomic Message Sequence (AMS)
- */
- enum ams_seq ams = ((1 << type) & PD_CTRL_AMS_START_MASK)
- ? AMS_START : AMS_RESPONSE;
-
-
- bit_len = pd_transmit(port, TCPCI_MSG_SOP, header, NULL, ams);
- if (debug_level >= 2)
- CPRINTF("C%d CTRL[%d]>%d\n", port, type, bit_len);
-
- return bit_len;
-}
-
-/*
- * Note: Source capabilities may either be in an existing AMS (ex. as a
- * response to Get_Source_Cap), or the beginning of an AMS for a power
- * negotiation.
- */
-static int send_source_cap(int port, enum ams_seq ams)
-{
- int bit_len;
-#if defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \
- defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT)
- const uint32_t *src_pdo;
- const int src_pdo_cnt = charge_manager_get_source_pdo(&src_pdo, port);
-#else
- const uint32_t *src_pdo = pd_src_pdo;
- const int src_pdo_cnt = pd_src_pdo_cnt;
-#endif
- uint16_t header;
-
- if (src_pdo_cnt == 0)
- /* No source capabilities defined, sink only */
- header = PD_HEADER(PD_CTRL_REJECT, pd[port].power_role,
- pd[port].data_role, pd[port].msg_id, 0,
- pd_get_rev(port, TCPCI_MSG_SOP), 0);
- else
- header = PD_HEADER(PD_DATA_SOURCE_CAP, pd[port].power_role,
- pd[port].data_role, pd[port].msg_id, src_pdo_cnt,
- pd_get_rev(port, TCPCI_MSG_SOP), 0);
-
- bit_len = pd_transmit(port, TCPCI_MSG_SOP, header, src_pdo, ams);
- if (debug_level >= 2)
- CPRINTF("C%d srcCAP>%d\n", port, bit_len);
-
- return bit_len;
-}
-
-#ifdef CONFIG_USB_PD_REV30
-static int send_battery_cap(int port, uint32_t *payload)
-{
- int bit_len;
- uint16_t msg[6] = {0, 0, 0, 0, 0, 0};
- uint16_t header = PD_HEADER(PD_EXT_BATTERY_CAP,
- pd[port].power_role,
- pd[port].data_role,
- pd[port].msg_id,
- 3, /* Number of Data Objects */
- pd[port].rev,
- 1 /* This is an exteded message */
- );
-
- /* Set extended header */
- msg[0] = PD_EXT_HEADER(0, /* Chunk Number */
- 0, /* Request Chunk */
- 9 /* Data Size in bytes */
- );
- /* Set VID */
- msg[1] = USB_VID_GOOGLE;
-
- /* Set PID */
- msg[2] = CONFIG_USB_PID;
-
- if (battery_is_present()) {
- /*
- * We only have one fixed battery,
- * so make sure batt cap ref is 0.
- */
- if (BATT_CAP_REF(payload[0]) != 0) {
- /* Invalid battery reference */
- msg[5] = 1;
- } else {
- uint32_t v;
- uint32_t c;
-
- /*
- * The Battery Design Capacity field shall return the
- * Battery’s design capacity in tenths of Wh. If the
- * Battery is Hot Swappable and is not present, the
- * Battery Design Capacity field shall be set to 0. If
- * the Battery is unable to report its Design Capacity,
- * it shall return 0xFFFF
- */
- msg[3] = 0xffff;
-
- /*
- * The Battery Last Full Charge Capacity field shall
- * return the Battery’s last full charge capacity in
- * tenths of Wh. If the Battery is Hot Swappable and
- * is not present, the Battery Last Full Charge Capacity
- * field shall be set to 0. If the Battery is unable to
- * report its Design Capacity, the Battery Last Full
- * Charge Capacity field shall be set to 0xFFFF.
- */
- msg[4] = 0xffff;
-
- if (battery_design_voltage(&v) == 0) {
- if (battery_design_capacity(&c) == 0) {
- /*
- * Wh = (c * v) / 1000000
- * 10th of a Wh = Wh * 10
- */
- msg[3] = DIV_ROUND_NEAREST((c * v),
- 100000);
- }
-
- if (battery_full_charge_capacity(&c) == 0) {
- /*
- * Wh = (c * v) / 1000000
- * 10th of a Wh = Wh * 10
- */
- msg[4] = DIV_ROUND_NEAREST((c * v),
- 100000);
- }
- }
- }
- }
-
- bit_len = pd_transmit(port, TCPCI_MSG_SOP, header, (uint32_t *)msg,
- AMS_RESPONSE);
- if (debug_level >= 2)
- CPRINTF("C%d batCap>%d\n", port, bit_len);
- return bit_len;
-}
-
-static int send_battery_status(int port, uint32_t *payload)
-{
- int bit_len;
- uint32_t msg = 0;
- uint16_t header = PD_HEADER(PD_DATA_BATTERY_STATUS,
- pd[port].power_role,
- pd[port].data_role,
- pd[port].msg_id,
- 1, /* Number of Data Objects */
- pd[port].rev,
- 0 /* This is NOT an extended message */
- );
-
- if (battery_is_present()) {
- /*
- * We only have one fixed battery,
- * so make sure batt cap ref is 0.
- */
- if (BATT_CAP_REF(payload[0]) != 0) {
- /* Invalid battery reference */
- msg |= BSDO_INVALID;
- } else {
- uint32_t v;
- uint32_t c;
-
- if (battery_design_voltage(&v) != 0 ||
- battery_remaining_capacity(&c) != 0) {
- msg |= BSDO_CAP(BSDO_CAP_UNKNOWN);
- } else {
- /*
- * Wh = (c * v) / 1000000
- * 10th of a Wh = Wh * 10
- */
- msg |= BSDO_CAP(DIV_ROUND_NEAREST((c * v),
- 100000));
- }
-
- /* Battery is present */
- msg |= BSDO_PRESENT;
-
- /*
- * For drivers that are not smart battery compliant,
- * battery_status() returns EC_ERROR_UNIMPLEMENTED and
- * the battery is assumed to be idle.
- */
- if (battery_status(&c) != 0) {
- msg |= BSDO_IDLE; /* assume idle */
- } else {
- if (c & STATUS_FULLY_CHARGED)
- /* Fully charged */
- msg |= BSDO_IDLE;
- else if (c & STATUS_DISCHARGING)
- /* Discharging */
- msg |= BSDO_DISCHARGING;
- /* else battery is charging.*/
- }
- }
- } else {
- msg = BSDO_CAP(BSDO_CAP_UNKNOWN);
- }
-
- bit_len = pd_transmit(port, TCPCI_MSG_SOP, header, &msg, AMS_RESPONSE);
- if (debug_level >= 2)
- CPRINTF("C%d batStat>%d\n", port, bit_len);
-
- return bit_len;
-}
-#endif
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-static void send_sink_cap(int port)
-{
- int bit_len;
- uint16_t header = PD_HEADER(PD_DATA_SINK_CAP, pd[port].power_role,
- pd[port].data_role, pd[port].msg_id, pd_snk_pdo_cnt,
- pd_get_rev(port, TCPCI_MSG_SOP), 0);
-
- bit_len = pd_transmit(port, TCPCI_MSG_SOP, header, pd_snk_pdo,
- AMS_RESPONSE);
- if (debug_level >= 2)
- CPRINTF("C%d snkCAP>%d\n", port, bit_len);
-}
-
-static int send_request(int port, uint32_t rdo)
-{
- int bit_len;
- uint16_t header = PD_HEADER(PD_DATA_REQUEST, pd[port].power_role,
- pd[port].data_role, pd[port].msg_id, 1,
- pd_get_rev(port, TCPCI_MSG_SOP), 0);
-
- /* Note: ams will need to be AMS_START if used for PPS keep alive */
- bit_len = pd_transmit(port, TCPCI_MSG_SOP, header, &rdo, AMS_RESPONSE);
- if (debug_level >= 2)
- CPRINTF("C%d REQ>%d\n", port, bit_len);
-
- return bit_len;
-}
-
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
-
-#ifdef CONFIG_COMMON_RUNTIME
-static int send_bist_cmd(int port)
-{
- /* currently only support sending bist carrier 2 */
- uint32_t bdo = BDO(BDO_MODE_CARRIER2, 0);
- int bit_len;
- uint16_t header = PD_HEADER(PD_DATA_BIST, pd[port].power_role,
- pd[port].data_role, pd[port].msg_id, 1,
- pd_get_rev(port, TCPCI_MSG_SOP), 0);
-
- bit_len = pd_transmit(port, TCPCI_MSG_SOP, header, &bdo, AMS_START);
- CPRINTF("C%d BIST>%d\n", port, bit_len);
-
- return bit_len;
-}
-#endif
-
-static void queue_vdm(int port, uint32_t *header, const uint32_t *data,
- int data_cnt, enum tcpci_msg_type type)
-{
- pd[port].vdo_count = data_cnt + 1;
- pd[port].vdo_data[0] = header[0];
- pd[port].xmit_type = type;
- memcpy(&pd[port].vdo_data[1], data,
- sizeof(uint32_t) * data_cnt);
- /* Set ready, pd task will actually send */
- pd[port].vdm_state = VDM_STATE_READY;
-}
-
-static void handle_vdm_request(int port, int cnt, uint32_t *payload,
- uint32_t head)
-{
- int rlen = 0;
- uint32_t *rdata;
- enum tcpci_msg_type rtype = TCPCI_MSG_SOP;
-
- if (pd[port].vdm_state == VDM_STATE_BUSY) {
- /* If UFP responded busy retry after timeout */
- if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_BUSY) {
- pd[port].vdm_timeout.val = get_time().val +
- PD_T_VDM_BUSY;
- pd[port].vdm_state = VDM_STATE_WAIT_RSP_BUSY;
- pd[port].vdo_retry = (payload[0] & ~VDO_CMDT_MASK) |
- CMDT_INIT;
- return;
- } else {
- pd[port].vdm_state = VDM_STATE_DONE;
-#ifdef CONFIG_USB_PD_REV30
- if (pd[port].rev == PD_REV30 &&
- pd[port].power_role == PD_ROLE_SOURCE &&
- pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT)
- sink_can_xmit(port, SINK_TX_OK);
-#endif
- }
- }
-
- if (PD_VDO_SVDM(payload[0]))
- rlen = pd_svdm(port, cnt, payload, &rdata, head, &rtype);
- else
- rlen = pd_custom_vdm(port, cnt, payload, &rdata);
-
- if (rlen > 0) {
- queue_vdm(port, rdata, &rdata[1], rlen - 1, rtype);
- return;
- }
-
- if (debug_level >= 2)
- CPRINTF("C%d Unhandled VDM VID %04x CMD %04x\n",
- port, PD_VDO_VID(payload[0]), payload[0] & 0xFFFF);
-}
-
-bool pd_is_disconnected(int port)
-{
- return pd[port].task_state == PD_STATE_SRC_DISCONNECTED
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- || pd[port].task_state == PD_STATE_SNK_DISCONNECTED
-#endif
- ;
-}
-
-static void pd_set_data_role(int port, enum pd_data_role role)
-{
- pd[port].data_role = role;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- pd_update_saved_port_flags(port, PD_BBRMFLG_DATA_ROLE, role);
-#endif /* defined(CONFIG_USB_PD_DUAL_ROLE) */
- pd_execute_data_swap(port, role);
-
- set_usb_mux_with_current_data_role(port);
- pd_update_roles(port);
-#ifdef CONFIG_BC12_DETECT_DATA_ROLE_TRIGGER
- /*
- * For BC1.2 detection that is triggered on data role change events
- * instead of VBUS changes, need to set an event to wake up the USB_CHG
- * task and indicate the current data role.
- */
- if (role == PD_ROLE_UFP)
- task_set_event(USB_CHG_PORT_TO_TASK_ID(port),
- USB_CHG_EVENT_DR_UFP);
- else if (role == PD_ROLE_DFP)
- task_set_event(USB_CHG_PORT_TO_TASK_ID(port),
- USB_CHG_EVENT_DR_DFP);
-#endif /* CONFIG_BC12_DETECT_DATA_ROLE_TRIGGER */
-}
-
-#ifdef CONFIG_USBC_VCONN
-static void pd_set_vconn_role(int port, int role)
-{
- if (role == PD_ROLE_VCONN_ON)
- pd[port].flags |= PD_FLAGS_VCONN_ON;
- else
- pd[port].flags &= ~PD_FLAGS_VCONN_ON;
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- pd_update_saved_port_flags(port, PD_BBRMFLG_VCONN_ROLE, role);
-#endif
-}
-#endif /* CONFIG_USBC_VCONN */
-
-void pd_execute_hard_reset(int port)
-{
- int hard_rst_tx = pd[port].last_state == PD_STATE_HARD_RESET_SEND;
-
- CPRINTF("C%d HARD RST %cX\n", port, hard_rst_tx ? 'T' : 'R');
-
- pd[port].msg_id = 0;
- invalidate_last_message_id(port);
- tcpm_set_rx_enable(port, 0);
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- if (pd_dfp_exit_mode(port, TCPCI_MSG_SOP, 0, 0))
- usb_mux_set_safe_mode(port);
-#endif
-
-#ifdef CONFIG_USB_PD_REV30
- pd[port].rev = PD_REV30;
-#endif
- /*
- * Fake set last state to hard reset to make sure that the next
- * state to run knows that we just did a hard reset.
- */
- pd[port].last_state = PD_STATE_HARD_RESET_EXECUTE;
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /*
- * If we are swapping to a source and have changed to Rp, restore back
- * to Rd and turn off vbus to match our power_role.
- */
- if (pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY ||
- pd[port].task_state == PD_STATE_SNK_SWAP_COMPLETE) {
- tcpm_set_cc(port, TYPEC_CC_RD);
- pd_power_supply_reset(port);
- }
-
- if (pd[port].power_role == PD_ROLE_SINK) {
- /* Initial data role for sink is UFP */
- pd_set_data_role(port, PD_ROLE_UFP);
-
- /* Clear the input current limit */
- pd_set_input_current_limit(port, 0, 0);
-#ifdef CONFIG_CHARGE_MANAGER
- charge_manager_set_ceil(port,
- CEIL_REQUESTOR_PD,
- CHARGE_CEIL_NONE);
-#endif /* CONFIG_CHARGE_MANAGER */
-
-#ifdef CONFIG_USBC_VCONN
- /*
- * Sink must turn off Vconn after a hard reset if it was being
- * sourced previously
- */
- if (pd[port].flags & PD_FLAGS_VCONN_ON) {
- set_vconn(port, 0);
- pd_set_vconn_role(port, PD_ROLE_VCONN_OFF);
- }
-#endif
-
- set_state(port, PD_STATE_SNK_HARD_RESET_RECOVER);
- return;
- } else {
- /* Initial data role for source is DFP */
- pd_set_data_role(port, PD_ROLE_DFP);
- }
-
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
-
- if (!hard_rst_tx)
- usleep(PD_T_PS_HARD_RESET);
-
- /* We are a source, cut power */
- pd_power_supply_reset(port);
- pd[port].src_recover = get_time().val + PD_T_SRC_RECOVER;
-#ifdef CONFIG_USBC_VCONN
- set_vconn(port, 0);
-#endif
- set_state(port, PD_STATE_SRC_HARD_RESET_RECOVER);
-}
-
-static void execute_soft_reset(int port)
-{
- invalidate_last_message_id(port);
- set_state(port, DUAL_ROLE_IF_ELSE(port, PD_STATE_SNK_DISCOVERY,
- PD_STATE_SRC_DISCOVERY));
- CPRINTF("C%d Soft Rst\n", port);
-}
-
-void pd_soft_reset(void)
-{
- int i;
-
- for (i = 0; i < board_get_usb_pd_port_count(); ++i)
- if (pd_is_connected(i)) {
- set_state(i, PD_STATE_SOFT_RESET);
- task_wake(PD_PORT_TO_TASK_ID(i));
- }
-}
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-/*
- * Request desired charge voltage from source.
- * Returns EC_SUCCESS on success or non-zero on failure.
- */
-static int pd_send_request_msg(int port, int always_send_request)
-{
- uint32_t rdo, curr_limit, supply_voltage;
- int res;
-
- /* Clear new power request */
- pd[port].new_power_request = 0;
-
- /* Build and send request RDO */
- pd_build_request(0, &rdo, &curr_limit, &supply_voltage, port);
-
- if (!always_send_request) {
- /* Don't re-request the same voltage */
- if (pd[port].prev_request_mv == supply_voltage)
- return EC_SUCCESS;
-#ifdef CONFIG_CHARGE_MANAGER
- /* Limit current to PD_MIN_MA during transition */
- else
- charge_manager_force_ceil(port, PD_MIN_MA);
-#endif
- }
-
- CPRINTF("C%d Req [%d] %dmV %dmA", port, RDO_POS(rdo),
- supply_voltage, curr_limit);
- if (rdo & RDO_CAP_MISMATCH)
- CPRINTF(" Mismatch");
- CPRINTF("\n");
-
- pd[port].curr_limit = curr_limit;
- pd[port].supply_voltage = supply_voltage;
- pd[port].prev_request_mv = supply_voltage;
- res = send_request(port, rdo);
- if (res < 0)
- return res;
- set_state(port, PD_STATE_SNK_REQUESTED);
- return EC_SUCCESS;
-}
-#endif
-
-static void pd_update_pdo_flags(int port, int pdo_cnt, uint32_t *pdos)
-{
- /* can only parse PDO flags if type is fixed */
- if ((pdos[0] & PDO_TYPE_MASK) != PDO_TYPE_FIXED)
- return;
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- if (pdos[0] & PDO_FIXED_DUAL_ROLE)
- pd[port].flags |= PD_FLAGS_PARTNER_DR_POWER;
- else
- pd[port].flags &= ~PD_FLAGS_PARTNER_DR_POWER;
-
- if (pdos[0] & PDO_FIXED_UNCONSTRAINED)
- pd[port].flags |= PD_FLAGS_PARTNER_UNCONSTR;
- else
- pd[port].flags &= ~PD_FLAGS_PARTNER_UNCONSTR;
-
- if (pdos[0] & PDO_FIXED_COMM_CAP)
- pd[port].flags |= PD_FLAGS_PARTNER_USB_COMM;
- else
- pd[port].flags &= ~PD_FLAGS_PARTNER_USB_COMM;
-#endif
-
- if (pdos[0] & PDO_FIXED_DATA_SWAP)
- pd[port].flags |= PD_FLAGS_PARTNER_DR_DATA;
- else
- pd[port].flags &= ~PD_FLAGS_PARTNER_DR_DATA;
-
- /*
- * Treat device as a dedicated charger (meaning we should charge
- * from it) if:
- * - it does not support power swap, or
- * - it is unconstrained power, or
- * - it presents at least 27 W of available power
- */
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) {
- uint32_t max_ma, max_mv, max_pdo, max_mw, unused;
-
- /*
- * Get max power that the partner offers (not necessarily what
- * this board will request)
- */
- pd_find_pdo_index(pdo_cnt, pdos, PD_REV3_MAX_VOLTAGE,
- &max_pdo);
- pd_extract_pdo_power(max_pdo, &max_ma, &max_mv, &unused);
- max_mw = max_ma * max_mv / 1000;
-
- if (!(pdos[0] & PDO_FIXED_DUAL_ROLE) ||
- (pdos[0] & PDO_FIXED_UNCONSTRAINED) ||
- max_mw >= PD_DRP_CHARGE_POWER_MIN)
- charge_manager_update_dualrole(port, CAP_DEDICATED);
- else
- charge_manager_update_dualrole(port, CAP_DUALROLE);
- }
-}
-
-static void handle_data_request(int port, uint32_t head,
- uint32_t *payload)
-{
- int type = PD_HEADER_TYPE(head);
- int cnt = PD_HEADER_CNT(head);
-
- switch (type) {
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- case PD_DATA_SOURCE_CAP:
- if ((pd[port].task_state == PD_STATE_SNK_DISCOVERY)
- || (pd[port].task_state == PD_STATE_SNK_TRANSITION)
- || (pd[port].task_state == PD_STATE_SNK_REQUESTED)
- || ((get_usb_pd_vbus_detect() ==
- USB_PD_VBUS_DETECT_NONE)
- && (pd[port].task_state ==
- PD_STATE_SNK_HARD_RESET_RECOVER))
- || (pd[port].task_state == PD_STATE_SNK_READY)) {
-#ifdef CONFIG_USB_PD_REV30
- /*
- * Only adjust sink rev if source rev is higher.
- */
- if (PD_HEADER_REV(head) < pd[port].rev)
- pd[port].rev = PD_HEADER_REV(head);
-#endif
- /* Port partner is now known to be PD capable */
- pd[port].flags |= PD_FLAGS_PREVIOUS_PD_CONN;
-
- /* src cap 0 should be fixed PDO */
- pd_update_pdo_flags(port, cnt, payload);
-
- pd_process_source_cap(port, cnt, payload);
-
- /* Source will resend source cap on failure */
- pd_send_request_msg(port, 1);
- }
- break;
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
- case PD_DATA_REQUEST:
- if ((pd[port].power_role == PD_ROLE_SOURCE) && (cnt == 1)) {
-#ifdef CONFIG_USB_PD_REV30
- /*
- * Adjust the rev level to what the sink supports. If
- * they're equal, no harm done.
- */
- pd[port].rev = PD_HEADER_REV(head);
-#endif
- if (!pd_check_requested_voltage(payload[0], port)) {
- if (send_control(port, PD_CTRL_ACCEPT) < 0)
- /*
- * if we fail to send accept, do
- * nothing and let sink timeout and
- * send hard reset
- */
- return;
-
- /* explicit contract is now in place */
- pd[port].flags |= PD_FLAGS_EXPLICIT_CONTRACT;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- pd_update_saved_port_flags(
- port, PD_BBRMFLG_EXPLICIT_CONTRACT, 1);
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
- pd[port].requested_idx = RDO_POS(payload[0]);
- set_state(port, PD_STATE_SRC_ACCEPTED);
- return;
- }
- }
- /* the message was incorrect or cannot be satisfied */
- send_control(port, PD_CTRL_REJECT);
- /* keep last contract in place (whether implicit or explicit) */
- set_state(port, PD_STATE_SRC_READY);
- break;
- case PD_DATA_BIST:
- /* If not in READY state, then don't start BIST */
- if (DUAL_ROLE_IF_ELSE(port,
- pd[port].task_state == PD_STATE_SNK_READY,
- pd[port].task_state == PD_STATE_SRC_READY)) {
- /* currently only support sending bist carrier mode 2 */
- if ((payload[0] >> 28) == 5) {
- /* bist data object mode is 2 */
- pd_transmit(port, TCPCI_MSG_TX_BIST_MODE_2, 0,
- NULL, AMS_RESPONSE);
- /* Set to appropriate port disconnected state */
- set_state(port, DUAL_ROLE_IF_ELSE(port,
- PD_STATE_SNK_DISCONNECTED,
- PD_STATE_SRC_DISCONNECTED));
- }
- }
- break;
- case PD_DATA_SINK_CAP:
- pd[port].flags |= PD_FLAGS_SNK_CAP_RECVD;
- /* snk cap 0 should be fixed PDO */
- pd_update_pdo_flags(port, cnt, payload);
- if (pd[port].task_state == PD_STATE_SRC_GET_SINK_CAP)
- set_state(port, PD_STATE_SRC_READY);
- break;
-#ifdef CONFIG_USB_PD_REV30
- case PD_DATA_BATTERY_STATUS:
- break;
- /* TODO : Add case PD_DATA_RESET for exiting USB4 */
-
- /*
- * TODO : Add case PD_DATA_ENTER_USB to accept or reject
- * Enter_USB request from port partner.
- */
-#endif
- case PD_DATA_VENDOR_DEF:
- handle_vdm_request(port, cnt, payload, head);
- break;
- default:
- CPRINTF("C%d Unhandled data message type %d\n", port, type);
- }
-}
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-void pd_request_power_swap(int port)
-{
- if (pd[port].task_state == PD_STATE_SRC_READY)
- set_state(port, PD_STATE_SRC_SWAP_INIT);
- else if (pd[port].task_state == PD_STATE_SNK_READY)
- set_state(port, PD_STATE_SNK_SWAP_INIT);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-#ifdef CONFIG_USBC_VCONN_SWAP
-void pd_request_vconn_swap(int port)
-{
- if (pd[port].task_state == PD_STATE_SRC_READY ||
- pd[port].task_state == PD_STATE_SNK_READY)
- set_state(port, PD_STATE_VCONN_SWAP_SEND);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void pd_try_vconn_src(int port)
-{
- /*
- * If we don't currently provide vconn, and we can supply it, send
- * a vconn swap request.
- */
- if (!(pd[port].flags & PD_FLAGS_VCONN_ON)) {
- if (pd_check_vconn_swap(port))
- pd_request_vconn_swap(port);
- }
-}
-#endif
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
-
-void pd_request_data_swap(int port)
-{
- if (DUAL_ROLE_IF_ELSE(port,
- pd[port].task_state == PD_STATE_SNK_READY,
- pd[port].task_state == PD_STATE_SRC_READY))
- set_state(port, PD_STATE_DR_SWAP);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-static void pd_set_power_role(int port, enum pd_power_role role)
-{
- pd[port].power_role = role;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- pd_update_saved_port_flags(port, PD_BBRMFLG_POWER_ROLE, role);
-#endif /* defined(CONFIG_USB_PD_DUAL_ROLE) */
-}
-
-static void pd_dr_swap(int port)
-{
- pd_set_data_role(port, !pd[port].data_role);
- pd[port].flags |= PD_FLAGS_CHECK_IDENTITY;
-}
-
-static void handle_ctrl_request(int port, uint32_t head,
- uint32_t *payload)
-{
- int type = PD_HEADER_TYPE(head);
- int res;
-
- switch (type) {
- case PD_CTRL_GOOD_CRC:
- /* should not get it */
- break;
- case PD_CTRL_PING:
- /* Nothing else to do */
- break;
- case PD_CTRL_GET_SOURCE_CAP:
- if (pd[port].task_state == PD_STATE_SRC_READY)
- set_state(port, PD_STATE_SRC_DISCOVERY);
- else {
- res = send_source_cap(port, AMS_RESPONSE);
- if ((res >= 0) &&
- (pd[port].task_state == PD_STATE_SRC_DISCOVERY))
- set_state(port, PD_STATE_SRC_NEGOCIATE);
- }
- break;
- case PD_CTRL_GET_SINK_CAP:
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- send_sink_cap(port);
-#else
- send_control(port, NOT_SUPPORTED(pd[port].rev));
-#endif
- break;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- case PD_CTRL_GOTO_MIN:
-#ifdef CONFIG_USB_PD_GIVE_BACK
- if (pd[port].task_state == PD_STATE_SNK_READY) {
- /*
- * Reduce power consumption now!
- *
- * The source will restore power to this sink
- * by sending a new source cap message at a
- * later time.
- */
- pd_snk_give_back(port, &pd[port].curr_limit,
- &pd[port].supply_voltage);
- set_state(port, PD_STATE_SNK_TRANSITION);
- }
-#endif
-
- break;
- case PD_CTRL_PS_RDY:
- if (pd[port].task_state == PD_STATE_SNK_SWAP_SRC_DISABLE) {
- set_state(port, PD_STATE_SNK_SWAP_STANDBY);
- } else if (pd[port].task_state == PD_STATE_SRC_SWAP_STANDBY) {
- /* reset message ID and swap roles */
- pd[port].msg_id = 0;
- invalidate_last_message_id(port);
- pd_set_power_role(port, PD_ROLE_SINK);
- pd_update_roles(port);
- /*
- * Give the state machine time to read VBUS as high.
- * Note: This is empirically determined, not strictly
- * part of the USB PD spec.
- */
- pd[port].vbus_debounce_time =
- get_time().val + PD_T_DEBOUNCE;
- set_state(port, PD_STATE_SNK_DISCOVERY);
-#ifdef CONFIG_USBC_VCONN_SWAP
- } else if (pd[port].task_state == PD_STATE_VCONN_SWAP_INIT) {
- /*
- * If VCONN is on, then this PS_RDY tells us it's
- * ok to turn VCONN off
- */
- if (pd[port].flags & PD_FLAGS_VCONN_ON)
- set_state(port, PD_STATE_VCONN_SWAP_READY);
-#endif
- } else if (pd[port].task_state == PD_STATE_SNK_DISCOVERY) {
- /* Don't know what power source is ready. Reset. */
- set_state(port, PD_STATE_HARD_RESET_SEND);
- } else if (pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY) {
- /* Do nothing, assume this is a redundant PD_RDY */
- } else if (pd[port].power_role == PD_ROLE_SINK) {
- /*
- * Give the source some time to send any messages before
- * we start our interrogation. Add some jitter of up to
- * ~192ms to prevent multiple collisions.
- */
- if (pd[port].task_state == PD_STATE_SNK_TRANSITION)
- pd[port].ready_state_holdoff_timer =
- get_time().val + SNK_READY_HOLD_OFF_US
- + (get_time().le.lo & 0xf) * 12 * MSEC;
-
- set_state(port, PD_STATE_SNK_READY);
- pd_set_input_current_limit(port, pd[port].curr_limit,
- pd[port].supply_voltage);
-#ifdef CONFIG_CHARGE_MANAGER
- /* Set ceiling based on what's negotiated */
- charge_manager_set_ceil(port,
- CEIL_REQUESTOR_PD,
- pd[port].curr_limit);
-#endif
- }
- break;
-#endif
- case PD_CTRL_REJECT:
- if (pd[port].task_state == PD_STATE_ENTER_USB) {
- if (!IS_ENABLED(CONFIG_USBC_SS_MUX))
- break;
-
- /*
- * Since Enter USB sets the mux state to SAFE mode,
- * resetting the mux state back to USB mode on
- * recieveing a NACK.
- */
- usb_mux_set(port, USB_PD_MUX_USB_ENABLED,
- USB_SWITCH_CONNECT, pd[port].polarity);
-
- set_state(port, READY_RETURN_STATE(port));
- break;
- }
- case PD_CTRL_WAIT:
- if (pd[port].task_state == PD_STATE_DR_SWAP) {
- if (type == PD_CTRL_WAIT) /* try again ... */
- pd[port].flags |= PD_FLAGS_CHECK_DR_ROLE;
- set_state(port, READY_RETURN_STATE(port));
- }
-#ifdef CONFIG_USBC_VCONN_SWAP
- else if (pd[port].task_state == PD_STATE_VCONN_SWAP_SEND)
- set_state(port, READY_RETURN_STATE(port));
-#endif
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- else if (pd[port].task_state == PD_STATE_SRC_SWAP_INIT)
- set_state(port, PD_STATE_SRC_READY);
- else if (pd[port].task_state == PD_STATE_SNK_SWAP_INIT)
- set_state(port, PD_STATE_SNK_READY);
- else if (pd[port].task_state == PD_STATE_SNK_REQUESTED) {
- /*
- * On reception of a WAIT message, transition to
- * PD_STATE_SNK_READY after PD_T_SINK_REQUEST ms to
- * send another request.
- *
- * On reception of a REJECT message, transition to
- * PD_STATE_SNK_READY but don't resend the request if
- * we already have a contract in place.
- *
- * On reception of a REJECT message without a contract,
- * transition to PD_STATE_SNK_DISCOVERY instead.
- */
- if (type == PD_CTRL_WAIT) {
- /*
- * Trigger a new power request when
- * we enter PD_STATE_SNK_READY
- */
- pd[port].new_power_request = 1;
-
- /*
- * After the request is triggered,
- * make sure the request is sent.
- */
- pd[port].prev_request_mv = 0;
-
- /*
- * Transition to PD_STATE_SNK_READY
- * after PD_T_SINK_REQUEST ms.
- */
- set_state_timeout(port,
- get_time().val +
- PD_T_SINK_REQUEST,
- PD_STATE_SNK_READY);
- } else {
- /* The request was rejected */
- const int in_contract =
- pd[port].flags &
- PD_FLAGS_EXPLICIT_CONTRACT;
- set_state(port,
- in_contract ? PD_STATE_SNK_READY
- : PD_STATE_SNK_DISCOVERY);
- }
- }
-#endif
- break;
- case PD_CTRL_ACCEPT:
- if (pd[port].task_state == PD_STATE_ENTER_USB) {
- if (!IS_ENABLED(CONFIG_USBC_SS_MUX))
- break;
-
- /* Connect the SBU and USB lines to the connector */
- if (IS_ENABLED(CONFIG_USBC_PPC_SBU))
- ppc_set_sbu(port, 1);
-
- /* Set usb mux to USB4 mode */
- usb_mux_set(port, USB_PD_MUX_USB4_ENABLED,
- USB_SWITCH_CONNECT, pd[port].polarity);
-
- set_state(port, READY_RETURN_STATE(port));
- } else if (pd[port].task_state == PD_STATE_SOFT_RESET) {
- /*
- * For the case that we sent soft reset in SNK_DISCOVERY
- * on startup due to VBUS never low, clear the flag.
- */
- pd[port].flags &= ~PD_FLAGS_VBUS_NEVER_LOW;
- execute_soft_reset(port);
- } else if (pd[port].task_state == PD_STATE_DR_SWAP) {
- /* switch data role */
- pd_dr_swap(port);
- set_state(port, READY_RETURN_STATE(port));
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-#ifdef CONFIG_USBC_VCONN_SWAP
- } else if (pd[port].task_state == PD_STATE_VCONN_SWAP_SEND) {
- /* switch vconn */
- set_state(port, PD_STATE_VCONN_SWAP_INIT);
-#endif
- } else if (pd[port].task_state == PD_STATE_SRC_SWAP_INIT) {
- /* explicit contract goes away for power swap */
- pd[port].flags &= ~PD_FLAGS_EXPLICIT_CONTRACT;
- pd_update_saved_port_flags(port,
- PD_BBRMFLG_EXPLICIT_CONTRACT,
- 0);
- set_state(port, PD_STATE_SRC_SWAP_SNK_DISABLE);
- } else if (pd[port].task_state == PD_STATE_SNK_SWAP_INIT) {
- /* explicit contract goes away for power swap */
- pd[port].flags &= ~PD_FLAGS_EXPLICIT_CONTRACT;
- pd_update_saved_port_flags(port,
- PD_BBRMFLG_EXPLICIT_CONTRACT,
- 0);
- set_state(port, PD_STATE_SNK_SWAP_SNK_DISABLE);
- } else if (pd[port].task_state == PD_STATE_SNK_REQUESTED) {
- /* explicit contract is now in place */
- pd[port].flags |= PD_FLAGS_EXPLICIT_CONTRACT;
- pd_update_saved_port_flags(port,
- PD_BBRMFLG_EXPLICIT_CONTRACT,
- 1);
- set_state(port, PD_STATE_SNK_TRANSITION);
-#endif
- }
- break;
- case PD_CTRL_SOFT_RESET:
- execute_soft_reset(port);
- pd[port].msg_id = 0;
- /* We are done, acknowledge with an Accept packet */
- send_control(port, PD_CTRL_ACCEPT);
- break;
- case PD_CTRL_PR_SWAP:
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- if (pd_check_power_swap(port)) {
- send_control(port, PD_CTRL_ACCEPT);
- /*
- * Clear flag for checking power role to avoid
- * immediately requesting another swap.
- */
- pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE;
- set_state(port,
- DUAL_ROLE_IF_ELSE(port,
- PD_STATE_SNK_SWAP_SNK_DISABLE,
- PD_STATE_SRC_SWAP_SNK_DISABLE));
- } else {
- send_control(port, PD_CTRL_REJECT);
- }
-#else
- send_control(port, NOT_SUPPORTED(pd[port].rev));
-#endif
- break;
- case PD_CTRL_DR_SWAP:
- if (pd_check_data_swap(port, pd[port].data_role)) {
- /*
- * Accept switch and perform data swap. Clear
- * flag for checking data role to avoid
- * immediately requesting another swap.
- */
- pd[port].flags &= ~PD_FLAGS_CHECK_DR_ROLE;
- if (send_control(port, PD_CTRL_ACCEPT) >= 0)
- pd_dr_swap(port);
- } else {
- send_control(port, PD_CTRL_REJECT);
-
- }
- break;
- case PD_CTRL_VCONN_SWAP:
-#ifdef CONFIG_USBC_VCONN_SWAP
- if (pd[port].task_state == PD_STATE_SRC_READY ||
- pd[port].task_state == PD_STATE_SNK_READY) {
- if (pd_check_vconn_swap(port)) {
- if (send_control(port, PD_CTRL_ACCEPT) > 0)
- set_state(port,
- PD_STATE_VCONN_SWAP_INIT);
- } else {
- send_control(port, PD_CTRL_REJECT);
- }
- }
-#else
- send_control(port, NOT_SUPPORTED(pd[port].rev));
-#endif
- break;
- default:
-#ifdef CONFIG_USB_PD_REV30
- send_control(port, PD_CTRL_NOT_SUPPORTED);
-#endif
- CPRINTF("C%d Unhandled ctrl message type %d\n", port, type);
- }
-}
-
-#ifdef CONFIG_USB_PD_REV30
-static void handle_ext_request(int port, uint16_t head, uint32_t *payload)
-{
- int type = PD_HEADER_TYPE(head);
-
- switch (type) {
- case PD_EXT_GET_BATTERY_CAP:
- send_battery_cap(port, payload);
- break;
- case PD_EXT_GET_BATTERY_STATUS:
- send_battery_status(port, payload);
- break;
- case PD_EXT_BATTERY_CAP:
- break;
- default:
- send_control(port, PD_CTRL_NOT_SUPPORTED);
- }
-}
-#endif
-
-static void handle_request(int port, uint32_t head,
- uint32_t *payload)
-{
- int cnt = PD_HEADER_CNT(head);
- int data_role = PD_HEADER_DROLE(head);
- int p;
-
- /* dump received packet content (only dump ping at debug level 3) */
- if ((debug_level == 2 && PD_HEADER_TYPE(head) != PD_CTRL_PING) ||
- debug_level >= 3) {
- CPRINTF("C%d RECV %04x/%d ", port, head, cnt);
- for (p = 0; p < cnt; p++)
- CPRINTF("[%d]%08x ", p, payload[p]);
- CPRINTF("\n");
- }
-
- /*
- * If we are in disconnected state, we shouldn't get a request. Do
- * a hard reset if we get one.
- */
- if (!pd_is_connected(port))
- set_state(port, PD_STATE_HARD_RESET_SEND);
-
- /*
- * When a data role conflict is detected, USB-C ErrorRecovery
- * actions shall be performed, and transitioning to unattached state
- * is one such legal action.
- */
- if (pd[port].data_role == data_role) {
- /*
- * If the port doesn't support removing the terminations, just
- * go to the unattached state.
- */
- if (tcpm_set_cc(port, TYPEC_CC_OPEN) == EC_SUCCESS) {
- /* Do not drive VBUS or VCONN. */
- pd_power_supply_reset(port);
-#ifdef CONFIG_USBC_VCONN
- set_vconn(port, 0);
-#endif /* defined(CONFIG_USBC_VCONN) */
- usleep(PD_T_ERROR_RECOVERY);
-
- /* Restore terminations. */
- tcpm_set_cc(port, DUAL_ROLE_IF_ELSE(port, TYPEC_CC_RD,
- TYPEC_CC_RP));
- }
- set_state(port,
- DUAL_ROLE_IF_ELSE(port,
- PD_STATE_SNK_DISCONNECTED,
- PD_STATE_SRC_DISCONNECTED));
- return;
- }
-
-#ifdef CONFIG_USB_PD_REV30
- /* Check if this is an extended chunked data message. */
- if (pd[port].rev == PD_REV30 && PD_HEADER_EXT(head)) {
- handle_ext_request(port, head, payload);
- return;
- }
-#endif
- if (cnt)
- handle_data_request(port, head, payload);
- else
- handle_ctrl_request(port, head, payload);
-}
-
-void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data,
- int count)
-{
- if (count > VDO_MAX_SIZE - 1) {
- CPRINTF("C%d VDM over max size\n", port);
- return;
- }
-
- /* set VDM header with VID & CMD */
- pd[port].vdo_data[0] = VDO(vid, ((vid & USB_SID_PD) == USB_SID_PD) ?
- 1 : (PD_VDO_CMD(cmd) <= CMD_ATTENTION), cmd);
-#ifdef CONFIG_USB_PD_REV30
- pd[port].vdo_data[0] |= VDO_SVDM_VERS(vdo_ver[pd[port].rev]);
-#endif
- queue_vdm(port, pd[port].vdo_data, data, count, TCPCI_MSG_SOP);
-
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-static inline int pdo_busy(int port)
-{
- /*
- * Note, main PDO state machine (pd_task) uses READY state exclusively
- * to denote port partners have successfully negociated a contract. All
- * other protocol actions force state transitions.
- */
- int rv = (pd[port].task_state != PD_STATE_SRC_READY);
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- rv &= (pd[port].task_state != PD_STATE_SNK_READY);
-#endif
- return rv;
-}
-
-static uint64_t vdm_get_ready_timeout(uint32_t vdm_hdr)
-{
- uint64_t timeout;
- int cmd = PD_VDO_CMD(vdm_hdr);
-
- /* its not a structured VDM command */
- if (!PD_VDO_SVDM(vdm_hdr))
- return 500*MSEC;
-
- switch (PD_VDO_CMDT(vdm_hdr)) {
- case CMDT_INIT:
- if ((cmd == CMD_ENTER_MODE) || (cmd == CMD_EXIT_MODE))
- timeout = PD_T_VDM_WAIT_MODE_E;
- else
- timeout = PD_T_VDM_SNDR_RSP;
- break;
- default:
- if ((cmd == CMD_ENTER_MODE) || (cmd == CMD_EXIT_MODE))
- timeout = PD_T_VDM_E_MODE;
- else
- timeout = PD_T_VDM_RCVR_RSP;
- break;
- }
- return timeout;
-}
-
-static void exit_tbt_mode_sop_prime(int port)
-{
- /* Exit Thunderbolt-Compatible mode SOP' */
- uint16_t header;
- int opos;
-
- if (!IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE))
- return;
-
- opos = pd_alt_mode(port, TCPCI_MSG_SOP, USB_VID_INTEL);
- if (opos <= 0)
- return;
-
- CPRINTS("C%d Cable exiting TBT Compat mode", port);
- /*
- * Note: TCPMv2 contemplates separate discovery structures for each SOP
- * type. TCPMv1 only uses one discovery structure, so all accesses
- * specify TCPCI_MSG_SOP.
- */
- if (pd_dfp_exit_mode(port, TCPCI_MSG_SOP, USB_VID_INTEL, opos))
- usb_mux_set_safe_mode(port);
- else
- return;
-
- header = PD_HEADER(PD_DATA_VENDOR_DEF, pd[port].power_role,
- pd[port].data_role, pd[port].msg_id,
- (int)pd[port].vdo_count,
- pd_get_rev(port, TCPCI_MSG_SOP), 0);
-
- pd[port].vdo_data[0] = VDO(USB_VID_INTEL, 1,
- CMD_EXIT_MODE | VDO_OPOS(opos));
-
- pd_transmit(port, TCPCI_MSG_SOP_PRIME, header, pd[port].vdo_data,
- AMS_START);
-
- usb_mux_set(port, USB_PD_MUX_USB_ENABLED, USB_SWITCH_CONNECT,
- polarity_rm_dts(pd_get_polarity(port)));
-}
-
-static void pd_vdm_send_state_machine(int port)
-{
- int res;
- uint16_t header;
- enum tcpci_msg_type msg_type = pd[port].xmit_type;
-
- switch (pd[port].vdm_state) {
- case VDM_STATE_READY:
- /* Only transmit VDM if connected. */
- if (!pd_is_connected(port)) {
- pd[port].vdm_state = VDM_STATE_ERR_BUSY;
- break;
- }
-
- /*
- * if there's traffic or we're not in PDO ready state don't send
- * a VDM.
- */
- if (pdo_busy(port))
- break;
-
- /*
- * To communicate with the cable plug, an explicit contract
- * should be established, VCONN should be enabled and data role
- * that can communicate with the cable plug should be in place.
- * For USB3.0, UFP/DFP can communicate whereas in case of
- * USB2.0 only DFP can talk to the cable plug.
- *
- * For communication between USB2.0 UFP and cable plug,
- * data role swap takes place during source and sink
- * negotiation and in case of failure, a soft reset is issued.
- */
- if ((msg_type == TCPCI_MSG_SOP_PRIME) ||
- (msg_type == TCPCI_MSG_SOP_PRIME_PRIME)) {
- /* Prepare SOP'/SOP'' header and send VDM */
- header = PD_HEADER(
- PD_DATA_VENDOR_DEF,
- PD_PLUG_FROM_DFP_UFP,
- 0,
- pd[port].msg_id,
- (int)pd[port].vdo_count,
- pd_get_rev(port, TCPCI_MSG_SOP),
- 0);
- res = pd_transmit(port, msg_type, header,
- pd[port].vdo_data, AMS_START);
- /*
- * In the case of SOP', if there is no response from
- * the cable, it's a non-emark cable and therefore the
- * pd flow should continue irrespective of cable
- * response, sending discover_identity so the pd flow
- * remains intact.
- *
- * In the case of SOP'', if there is no response from
- * the cable, exit Thunderbolt-Compatible mode
- * discovery, reset the mux state since, the mux will
- * be set to a safe state before entering
- * Thunderbolt-Compatible mode and enter the default
- * mode.
- */
- if (res < 0) {
- header = PD_HEADER(PD_DATA_VENDOR_DEF,
- pd[port].power_role,
- pd[port].data_role,
- pd[port].msg_id,
- (int)pd[port].vdo_count,
- pd_get_rev
- (port, TCPCI_MSG_SOP),
- 0);
-
- if ((msg_type == TCPCI_MSG_SOP_PRIME_PRIME) &&
- IS_ENABLED(CONFIG_USBC_SS_MUX)) {
- exit_tbt_mode_sop_prime(port);
- } else if (msg_type == TCPCI_MSG_SOP_PRIME) {
- pd[port].vdo_data[0] = VDO(USB_SID_PD,
- 1, CMD_DISCOVER_SVID);
- }
- res = pd_transmit(port, TCPCI_MSG_SOP, header,
- pd[port].vdo_data, AMS_START);
- reset_pd_cable(port);
- }
- } else {
- /* Prepare SOP header and send VDM */
- header = PD_HEADER(PD_DATA_VENDOR_DEF,
- pd[port].power_role,
- pd[port].data_role,
- pd[port].msg_id,
- (int)pd[port].vdo_count,
- pd_get_rev(port, TCPCI_MSG_SOP), 0);
- res = pd_transmit(port, TCPCI_MSG_SOP, header,
- pd[port].vdo_data, AMS_START);
- }
-
- if (res < 0) {
- pd[port].vdm_state = VDM_STATE_ERR_SEND;
- } else {
- pd[port].vdm_state = VDM_STATE_BUSY;
- pd[port].vdm_timeout.val = get_time().val +
- vdm_get_ready_timeout(pd[port].vdo_data[0]);
- }
- break;
- case VDM_STATE_WAIT_RSP_BUSY:
- /* wait and then initiate request again */
- if (get_time().val > pd[port].vdm_timeout.val) {
- pd[port].vdo_data[0] = pd[port].vdo_retry;
- pd[port].vdo_count = 1;
- pd[port].vdm_state = VDM_STATE_READY;
- }
- break;
- case VDM_STATE_BUSY:
- /* Wait for VDM response or timeout */
- if (pd[port].vdm_timeout.val &&
- (get_time().val > pd[port].vdm_timeout.val)) {
- pd[port].vdm_state = VDM_STATE_ERR_TMOUT;
- }
- break;
- case VDM_STATE_ERR_SEND:
- /* Sending the VDM failed, so try again. */
- CPRINTF("C%d VDMretry\n", port);
- pd[port].vdm_state = VDM_STATE_READY;
- break;
- default:
- break;
- }
-}
-
-#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO
-static inline void pd_dev_dump_info(uint16_t dev_id, uint8_t *hash)
-{
- int j;
- ccprintf("DevId:%d.%d Hash:", HW_DEV_ID_MAJ(dev_id),
- HW_DEV_ID_MIN(dev_id));
- for (j = 0; j < PD_RW_HASH_SIZE; j += 4) {
- ccprintf(" 0x%02x%02x%02x%02x", hash[j + 3], hash[j + 2],
- hash[j + 1], hash[j]);
- }
- ccprintf("\n");
-}
-#endif /* CONFIG_CMD_PD_DEV_DUMP_INFO */
-
-int pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash,
- uint32_t current_image)
-{
-#ifdef CONFIG_COMMON_RUNTIME
- int i;
-#endif
-
- pd[port].dev_id = dev_id;
- memcpy(pd[port].dev_rw_hash, rw_hash, PD_RW_HASH_SIZE);
-#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO
- if (debug_level >= 2)
- pd_dev_dump_info(dev_id, (uint8_t *)rw_hash);
-#endif
- pd[port].current_image = current_image;
-
-#ifdef CONFIG_COMMON_RUNTIME
- /* Search table for matching device / hash */
- for (i = 0; i < RW_HASH_ENTRIES; i++)
- if (dev_id == rw_hash_table[i].dev_id)
- return !memcmp(rw_hash,
- rw_hash_table[i].dev_rw_hash,
- PD_RW_HASH_SIZE);
-#endif
- return 0;
-}
-
-void pd_dev_get_rw_hash(int port, uint16_t *dev_id, uint8_t *rw_hash,
- uint32_t *current_image)
-{
- *dev_id = pd[port].dev_id;
- *current_image = pd[port].current_image;
- if (*dev_id)
- memcpy(rw_hash, pd[port].dev_rw_hash, PD_RW_HASH_SIZE);
-}
-
-__maybe_unused static void exit_supported_alt_mode(int port)
-{
- int i;
-
- if (!IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- return;
-
- for (i = 0; i < supported_modes_cnt; i++) {
- int opos = pd_alt_mode(port, TCPCI_MSG_SOP,
- supported_modes[i].svid);
-
- if (opos > 0 && pd_dfp_exit_mode(port, TCPCI_MSG_SOP,
- supported_modes[i].svid, opos)) {
- CPRINTS("C%d Exiting ALT mode with SVID = 0x%x", port,
- supported_modes[i].svid);
- usb_mux_set_safe_mode(port);
- pd_send_vdm(port, supported_modes[i].svid,
- CMD_EXIT_MODE | VDO_OPOS(opos), NULL, 0);
- /* Wait for an ACK from port-partner */
- pd_vdm_send_state_machine(port);
- }
- }
-}
-
-#ifdef CONFIG_POWER_COMMON
-static void handle_new_power_state(int port)
-{
-
- if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) {
- /*
- * The SoC will negotiate the alternate mode again when
- * it boots up.
- */
- exit_supported_alt_mode(port);
- }
-#ifdef CONFIG_USBC_VCONN_SWAP
- else {
- /* Request for Vconn Swap */
- pd_try_vconn_src(port);
- }
-#endif
- /* Ensure mux is set properly after chipset transition */
- set_usb_mux_with_current_data_role(port);
-}
-#endif /* CONFIG_POWER_COMMON */
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-enum pd_dual_role_states pd_get_dual_role(int port)
-{
- return drp_state[port];
-}
-
-#ifdef CONFIG_USB_PD_TRY_SRC
-static void pd_update_try_source(void)
-{
- int i;
-
- pd_try_src_enable = pd_is_try_source_capable();
-
- /*
- * Clear this flag to cover case where a TrySrc
- * mode went from enabled to disabled and trying_source
- * was active at that time.
- */
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- pd[i].flags &= ~PD_FLAGS_TRY_SRC;
-}
-#endif /* CONFIG_USB_PD_TRY_SRC */
-
-#ifdef CONFIG_USB_PD_RESET_MIN_BATT_SOC
-static void pd_update_snk_reset(void)
-{
- int i;
- int batt_soc = usb_get_battery_soc();
-
- if (batt_soc < CONFIG_USB_PD_RESET_MIN_BATT_SOC ||
- battery_get_disconnect_state() != BATTERY_NOT_DISCONNECTED)
- return;
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- if (pd[i].flags & PD_FLAGS_SNK_WAITING_BATT) {
- /*
- * Battery has gained sufficient charge to kick off PD
- * negotiation and withstand a hard reset. Clear the
- * flag and let reset begin if task is waiting in
- * SNK_DISCOVERY.
- */
- pd[i].flags &= ~PD_FLAGS_SNK_WAITING_BATT;
-
- if (pd[i].task_state == PD_STATE_SNK_DISCOVERY) {
- CPRINTS("C%d: Starting soft reset timer", i);
- set_state_timeout(i,
- get_time().val + PD_T_SINK_WAIT_CAP,
- PD_STATE_SOFT_RESET);
- }
- }
- }
-}
-#endif
-
-#if defined(CONFIG_USB_PD_TRY_SRC) || defined(CONFIG_USB_PD_RESET_MIN_BATT_SOC)
-static void pd_update_battery_soc_change(void)
-{
-#ifdef CONFIG_USB_PD_TRY_SRC
- pd_update_try_source();
-#endif
-
-#ifdef CONFIG_USB_PD_RESET_MIN_BATT_SOC
- pd_update_snk_reset();
-#endif
-}
-DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, pd_update_battery_soc_change,
- HOOK_PRIO_DEFAULT);
-#endif /* CONFIG_USB_PD_TRY_SRC || CONFIG_USB_PD_RESET_MIN_BATT_SOC */
-
-static inline void pd_set_dual_role_no_wakeup(int port,
- enum pd_dual_role_states state)
-{
- drp_state[port] = state;
-
-#ifdef CONFIG_USB_PD_TRY_SRC
- pd_update_try_source();
-#endif
-}
-
-void pd_set_dual_role(int port, enum pd_dual_role_states state)
-{
- pd_set_dual_role_no_wakeup(port, state);
-
- /* Wake task up to process change */
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_UPDATE_DUAL_ROLE);
-}
-
-static int pd_is_power_swapping(int port)
-{
- /* return true if in the act of swapping power roles */
- return pd[port].task_state == PD_STATE_SNK_SWAP_SNK_DISABLE ||
- pd[port].task_state == PD_STATE_SNK_SWAP_SRC_DISABLE ||
- pd[port].task_state == PD_STATE_SNK_SWAP_STANDBY ||
- pd[port].task_state == PD_STATE_SNK_SWAP_COMPLETE ||
- pd[port].task_state == PD_STATE_SRC_SWAP_SNK_DISABLE ||
- pd[port].task_state == PD_STATE_SRC_SWAP_SRC_DISABLE ||
- pd[port].task_state == PD_STATE_SRC_SWAP_STANDBY;
-}
-
-/* This must only be called from the PD task */
-static void pd_update_dual_role_config(int port)
-{
- /*
- * Change to sink if port is currently a source AND (new DRP
- * state is force sink OR new DRP state is toggle off and we are in the
- * source disconnected state).
- */
- if (pd[port].power_role == PD_ROLE_SOURCE &&
- (drp_state[port] == PD_DRP_FORCE_SINK
- || (drp_state[port] == PD_DRP_TOGGLE_OFF
- && pd[port].task_state == PD_STATE_SRC_DISCONNECTED))) {
- pd_set_power_role(port, PD_ROLE_SINK);
- set_state(port, PD_STATE_SNK_DISCONNECTED);
- tcpm_set_cc(port, TYPEC_CC_RD);
- /* Make sure we're not sourcing VBUS. */
- pd_power_supply_reset(port);
- }
-
- /*
- * Change to source if port is currently a sink and the
- * new DRP state is force source. If we are performing
- * power swap we won't change anything because
- * changing state will disrupt power swap process
- * and we are power swapping to desired power role.
- */
- if (pd[port].power_role == PD_ROLE_SINK &&
- drp_state[port] == PD_DRP_FORCE_SOURCE &&
- !pd_is_power_swapping(port)) {
- pd_set_power_role(port, PD_ROLE_SOURCE);
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- tcpm_set_cc(port, TYPEC_CC_RP);
- }
-}
-
-/*
- * Provide Rp to ensure the partner port is in a known state (eg. not
- * PD negotiated, not sourcing 20V).
- */
-static void pd_partner_port_reset(int port)
-{
- uint64_t timeout;
- uint8_t flags;
-
- /*
- * If there is no contract in place (or if we fail to read the BBRAM
- * flags), there is no need to reset the partner.
- */
- if (pd_get_saved_port_flags(port, &flags) != EC_SUCCESS ||
- !(flags & PD_BBRMFLG_EXPLICIT_CONTRACT))
- return;
-
- /*
- * If we reach here, an explicit contract is in place.
- *
- * If PD communications are allowed, don't apply Rp. We'll issue a
- * SoftReset later on and renegotiate our contract. This particular
- * condition only applies to unlocked RO images with an explicit
- * contract in place.
- */
- if (pd_comm_is_enabled(port))
- return;
-
- /* If we just lost power, don't apply Rp. */
- if (system_get_reset_flags() &
- (EC_RESET_FLAG_BROWNOUT | EC_RESET_FLAG_POWER_ON))
- return;
-
- /*
- * Clear the active contract bit before we apply Rp in case we
- * intentionally brown out because we cut off our only power supply.
- */
- pd_update_saved_port_flags(port, PD_BBRMFLG_EXPLICIT_CONTRACT, 0);
-
- /* Provide Rp for 200 msec. or until we no longer have VBUS. */
- CPRINTF("C%d Apply Rp!\n", port);
- cflush();
- tcpm_set_cc(port, TYPEC_CC_RP);
- timeout = get_time().val + 200 * MSEC;
-
- while (get_time().val < timeout && pd_is_vbus_present(port))
- msleep(10);
-}
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
-
-enum pd_power_role pd_get_power_role(int port)
-{
- return pd[port].power_role;
-}
-
-enum pd_data_role pd_get_data_role(int port)
-{
- return pd[port].data_role;
-}
-
-enum pd_cc_states pd_get_task_cc_state(int port)
-{
- return pd[port].cc_state;
-}
-
-uint8_t pd_get_task_state(int port)
-{
- return pd[port].task_state;
-}
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-uint32_t pd_get_requested_voltage(int port)
-{
- return pd[port].supply_voltage;
-}
-
-uint32_t pd_get_requested_current(int port)
-{
- return pd[port].curr_limit;
-}
-#endif
-
-const char *pd_get_task_state_name(int port)
-{
-#ifdef CONFIG_USB_PD_TCPMV1_DEBUG
- if (debug_level > 0)
- return pd_state_names[pd[port].task_state];
-#endif
- return "";
-}
-
-bool pd_get_vconn_state(int port)
-{
- return !!(pd[port].flags & PD_FLAGS_VCONN_ON);
-}
-
-bool pd_get_partner_dual_role_power(int port)
-{
- return !!(pd[port].flags & PD_FLAGS_PARTNER_DR_POWER);
-}
-
-bool pd_get_partner_unconstr_power(int port)
-{
- return !!(pd[port].flags & PD_FLAGS_PARTNER_UNCONSTR);
-}
-
-enum tcpc_cc_polarity pd_get_polarity(int port)
-{
- return pd[port].polarity;
-}
-
-bool pd_get_partner_data_swap_capable(int port)
-{
- /* return data swap capable status of port partner */
- return !!(pd[port].flags & PD_FLAGS_PARTNER_DR_DATA);
-}
-
-#ifdef CONFIG_COMMON_RUNTIME
-void pd_comm_enable(int port, int enable)
-{
- /* We don't check port >= CONFIG_USB_PD_PORT_MAX_COUNT deliberately */
- pd_comm_enabled[port] = enable;
-
- /* If type-C connection, then update the TCPC RX enable */
- if (pd_is_connected(port))
- tcpm_set_rx_enable(port, enable);
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /*
- * If communications are enabled, start hard reset timer for
- * any port in PD_SNK_DISCOVERY.
- */
- if (enable && pd[port].task_state == PD_STATE_SNK_DISCOVERY)
- set_state_timeout(port,
- get_time().val + PD_T_SINK_WAIT_CAP,
- PD_STATE_HARD_RESET_SEND);
-#endif
-}
-#endif
-
-void pd_ping_enable(int port, int enable)
-{
- if (enable)
- pd[port].flags |= PD_FLAGS_PING_ENABLED;
- else
- pd[port].flags &= ~PD_FLAGS_PING_ENABLED;
-}
-
-__overridable uint8_t board_get_src_dts_polarity(int port)
-{
- /*
- * If the port in SRC DTS, the polarity is determined by the board,
- * i.e. what Rp impedance the CC lines are pulled. If this function
- * is not overridden, assume CC1 is primary.
- */
- return 0;
-}
-
-#if defined(CONFIG_CHARGE_MANAGER)
-
-/**
- * Signal power request to indicate a charger update that affects the port.
- */
-void pd_set_new_power_request(int port)
-{
- pd[port].new_power_request = 1;
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-#endif /* CONFIG_CHARGE_MANAGER */
-
-#if defined(CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP) && defined(CONFIG_USBC_SS_MUX)
-/*
- * Backwards compatible DFP does not support USB SS because it applies VBUS
- * before debouncing CC and setting USB SS muxes, but SS detection will fail
- * before we are done debouncing CC.
- */
-#error "Backwards compatible DFP does not support USB"
-#endif
-
-#ifdef CONFIG_COMMON_RUNTIME
-
-/* Initialize globals based on system state. */
-static void pd_init_tasks(void)
-{
- static int initialized;
- int enable = 1;
- int i;
-
- /* Initialize globals once, for all PD tasks. */
- if (initialized)
- return;
-
-#if defined(HAS_TASK_CHIPSET) && defined(CONFIG_USB_PD_DUAL_ROLE)
- /* Set dual-role state based on chipset power state */
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- drp_state[i] = PD_DRP_FORCE_SINK;
- else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND))
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- drp_state[i] = PD_DRP_TOGGLE_OFF;
- else /* CHIPSET_STATE_ON */
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- drp_state[i] = PD_DRP_TOGGLE_ON;
-#endif
-
-#if defined(CONFIG_USB_PD_COMM_DISABLED)
- enable = 0;
-#elif defined(CONFIG_USB_PD_COMM_LOCKED)
- /* Disable PD communication if we're in RO, WP is enabled, and EFS
- * didn't register NO_BOOT. */
- if (!system_is_in_rw() && system_is_locked() && !vboot_allow_usb_pd())
- enable = 0;
-#endif
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- pd_comm_enabled[i] = enable;
- CPRINTS("PD comm %sabled", enable ? "en" : "dis");
-
- initialized = 1;
-}
-#endif /* CONFIG_COMMON_RUNTIME */
-
-#if !defined(CONFIG_USB_PD_TCPC) && defined(CONFIG_USB_PD_DUAL_ROLE)
-static int pd_restart_tcpc(int port)
-{
- if (board_set_tcpc_power_mode) {
- /* force chip reset */
- board_set_tcpc_power_mode(port, 0);
- }
- return tcpm_init(port);
-}
-#endif
-
-static void pd_send_enter_usb(int port, int *timeout)
-{
- uint32_t usb4_payload;
- uint16_t header;
- int res;
-
- /*
- * TODO: Enable Enter USB for cables (SOP').
- * This is needed for active cables
- */
- if (!IS_ENABLED(CONFIG_USBC_SS_MUX) ||
- !IS_ENABLED(CONFIG_USB_PD_USB4) ||
- !IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- return;
-
- usb4_payload = get_enter_usb_msg_payload(port);
-
- header = PD_HEADER(PD_DATA_ENTER_USB,
- pd[port].power_role,
- pd[port].data_role,
- pd[port].msg_id,
- 1,
- PD_REV30,
- 0);
-
- res = pd_transmit(port, TCPCI_MSG_SOP, header, &usb4_payload,
- AMS_START);
- if (res < 0) {
- *timeout = 10*MSEC;
- /*
- * If failed to get goodCRC, send soft reset, otherwise ignore
- * failure.
- */
- set_state(port, res == -1 ?
- PD_STATE_SOFT_RESET :
- READY_RETURN_STATE(port));
- return;
- }
-
- /* Disable Enter USB4 mode prevent re-entry */
- disable_enter_usb4_mode(port);
-
- set_state(port, PD_STATE_ENTER_USB);
-}
-
-void pd_task(void *u)
-{
- uint32_t head;
- int port = TASK_ID_TO_PD_PORT(task_get_current());
- uint32_t payload[7];
- int timeout = 10*MSEC;
- enum tcpc_cc_voltage_status cc1, cc2;
- int res, incoming_packet = 0;
- int hard_reset_count = 0;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- uint64_t next_role_swap = PD_T_DRP_SNK;
- uint8_t saved_flgs = 0;
-#ifndef CONFIG_USB_PD_VBUS_DETECT_NONE
- int snk_hard_reset_vbus_off = 0;
-#endif
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- const int auto_toggle_supported = tcpm_auto_toggle_supported(port);
-#endif
-#if defined(CONFIG_CHARGE_MANAGER)
- typec_current_t typec_curr = 0, typec_curr_change = 0;
-#endif /* CONFIG_CHARGE_MANAGER */
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
- enum pd_states this_state;
- enum pd_cc_states new_cc_state;
- timestamp_t now;
- uint64_t next_src_cap = 0;
- int caps_count = 0, hard_reset_sent = 0;
- int snk_cap_count = 0;
- int evt;
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /*
- * Set the ports in Low Power Mode so that other tasks wait until
- * TCPC is initialized and ready.
- */
- pd[port].flags |= PD_FLAGS_LPM_ENGAGED;
-#endif
-
-#ifdef CONFIG_COMMON_RUNTIME
- pd_init_tasks();
-#endif
-
- /*
- * Ensure the power supply is in the default state and ensure we are not
- * sourcing Vconn
- */
- pd_power_supply_reset(port);
-#ifdef CONFIG_USBC_VCONN
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /*
- * If we were previously a sink but also the VCONN source, we should
- * still continue to source VCONN. Otherwise, we should turn off VCONN
- * since we are also going to turn off VBUS.
- */
- if (pd_comm_is_enabled(port) &&
- (pd_get_saved_port_flags(port, &saved_flgs) == EC_SUCCESS) &&
- ((saved_flgs & PD_BBRMFLG_POWER_ROLE) == PD_ROLE_SINK) &&
- (saved_flgs & PD_BBRMFLG_EXPLICIT_CONTRACT) &&
- (saved_flgs & PD_BBRMFLG_VCONN_ROLE))
- set_vconn(port, 1);
- else
-#endif
- set_vconn(port, 0);
-#endif
-
-#ifdef CONFIG_USB_PD_TCPC_BOARD_INIT
- /* Board specific TCPC init */
- board_tcpc_init();
-#endif
-
- /* Initialize TCPM driver and wait for TCPC to be ready */
- res = reset_device_and_notify(port);
- invalidate_last_message_id(port);
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- pd_partner_port_reset(port);
-#endif
-
- this_state = res ? PD_STATE_SUSPENDED : PD_DEFAULT_STATE(port);
-#ifndef CONFIG_USB_PD_TCPC
- if (!res) {
- struct ec_response_pd_chip_info_v1 info;
-
- if (tcpm_get_chip_info(port, 0, &info) ==
- EC_SUCCESS) {
- CPRINTS("TCPC p%d VID:0x%x PID:0x%x DID:0x%x "
- "FWV:0x%" PRIx64,
- port, info.vendor_id, info.product_id,
- info.device_id, info.fw_version_number);
- }
- }
-#endif
-
-#ifdef CONFIG_USB_PD_REV30
- /* Set Revision to highest */
- pd[port].rev = PD_REV30;
-#endif
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /*
- * If VBUS is high, then initialize flag for VBUS has always been
- * present. This flag is used to maintain a PD connection after a
- * reset by sending a soft reset.
- */
- pd[port].flags |=
- pd_is_vbus_present(port) ? PD_FLAGS_VBUS_NEVER_LOW : 0;
-#endif
-
- /* Disable TCPC RX until connection is established */
- tcpm_set_rx_enable(port, 0);
-
-#ifdef CONFIG_USBC_SS_MUX
- /* Initialize USB mux to its default state */
- usb_mux_init(port);
-#endif
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /*
- * If there's an explicit contract in place, let's restore the data and
- * power roles such that any messages we send to the port partner will
- * still be valid.
- */
- if (pd_comm_is_enabled(port) &&
- (pd_get_saved_port_flags(port, &saved_flgs) == EC_SUCCESS) &&
- (saved_flgs & PD_BBRMFLG_EXPLICIT_CONTRACT)) {
- /* Only attempt to maintain previous sink contracts */
- if ((saved_flgs & PD_BBRMFLG_POWER_ROLE) == PD_ROLE_SINK) {
- pd_set_power_role(port,
- (saved_flgs & PD_BBRMFLG_POWER_ROLE) ?
- PD_ROLE_SOURCE : PD_ROLE_SINK);
- pd_set_data_role(port,
- (saved_flgs & PD_BBRMFLG_DATA_ROLE) ?
- PD_ROLE_DFP : PD_ROLE_UFP);
-#ifdef CONFIG_USBC_VCONN
- pd_set_vconn_role(port,
- (saved_flgs & PD_BBRMFLG_VCONN_ROLE) ?
- PD_ROLE_VCONN_ON : PD_ROLE_VCONN_OFF);
-#endif /* CONFIG_USBC_VCONN */
-
- /*
- * Since there is an explicit contract in place, let's
- * issue a SoftReset such that we can renegotiate with
- * our port partner in order to synchronize our state
- * machines.
- */
- this_state = PD_STATE_SOFT_RESET;
-
- /*
- * Re-discover any alternate modes we may have been
- * using with this port partner.
- */
- pd[port].flags |= PD_FLAGS_CHECK_IDENTITY;
- } else {
- /*
- * Vbus was turned off during the power supply reset
- * earlier, so clear the contract flag and re-start as
- * default role
- */
- pd_update_saved_port_flags(port,
- PD_BBRMFLG_EXPLICIT_CONTRACT, 0);
-
- }
- /*
- * Set the TCPC reset event such that we can set our CC
- * terminations, determine polarity, and enable RX so we
- * can hear back from our port partner if maintaining our old
- * connection.
- */
- task_set_event(task_get_current(), PD_EVENT_TCPC_RESET);
- }
-#endif /* defined(CONFIG_USB_PD_DUAL_ROLE) */
- /* Set the power role if we haven't already. */
- if (this_state != PD_STATE_SOFT_RESET)
- pd_set_power_role(port, PD_ROLE_DEFAULT(port));
-
- /* Initialize PD protocol state variables for each port. */
- pd[port].vdm_state = VDM_STATE_DONE;
- set_state(port, this_state);
- tcpm_select_rp_value(port, CONFIG_USB_PD_PULLUP);
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /*
- * If we're not in an explicit contract, set our terminations to match
- * our default power role.
- */
- if (!(saved_flgs & PD_BBRMFLG_EXPLICIT_CONTRACT))
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
- tcpm_set_cc(port, PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE ?
- TYPEC_CC_RP : TYPEC_CC_RD);
-
-#ifdef CONFIG_USBC_PPC
- /*
- * Wait to initialize the PPC after setting the correct Rd values in
- * the TCPC otherwise the TCPC might not be pulling the CC lines down
- * when the PPC connects the CC lines from the USB connector to the
- * TCPC cause the source to drop Vbus causing a brown out.
- */
- ppc_init(port);
-#endif
-
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- /* Initialize PD Policy engine */
- pd_dfp_discovery_init(port);
- pd_dfp_mode_init(port);
-#endif
-
-#ifdef CONFIG_CHARGE_MANAGER
- /* Initialize PD and type-C supplier current limits to 0 */
- pd_set_input_current_limit(port, 0, 0);
- typec_set_input_current_limit(port, 0, 0);
- charge_manager_update_dualrole(port, CAP_UNKNOWN);
-#endif
-
- /*
- * Since most boards configure the TCPC interrupt as edge
- * and it is possible that the interrupt line was asserted between init
- * and calling set_state, we need to process any pending interrupts now.
- * Otherwise future interrupts will never fire because another edge
- * never happens. Note this needs to happen after set_state() is called.
- */
- if (IS_ENABLED(CONFIG_HAS_TASK_PD_INT))
- schedule_deferred_pd_interrupt(port);
-
- while (1) {
- /* process VDM messages last */
- pd_vdm_send_state_machine(port);
-
- /* Verify board specific health status : current, voltages... */
- res = pd_board_checks();
- if (res != EC_SUCCESS) {
- /* cut the power */
- pd_execute_hard_reset(port);
- /* notify the other side of the issue */
- pd_transmit(port, TCPCI_MSG_TX_HARD_RESET, 0, NULL,
- AMS_START);
- }
-
- /* wait for next event/packet or timeout expiration */
- evt = task_wait_event(timeout);
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- if (evt & (PD_EXIT_LOW_POWER_EVENT_MASK | TASK_EVENT_WAKE))
- exit_low_power_mode(port);
- if (evt & PD_EVENT_DEVICE_ACCESSED)
- handle_device_access(port);
-#endif
-#ifdef CONFIG_POWER_COMMON
- if (evt & PD_EVENT_POWER_STATE_CHANGE)
- handle_new_power_state(port);
-#endif
-
-#if defined(CONFIG_USB_PD_ALT_MODE_DFP)
- if (evt & PD_EVENT_SYSJUMP) {
- exit_supported_alt_mode(port);
- notify_sysjump_ready();
- }
-#endif
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- if (evt & PD_EVENT_UPDATE_DUAL_ROLE)
- pd_update_dual_role_config(port);
-#endif
-
-#ifdef CONFIG_USB_PD_TCPC
- /*
- * run port controller task to check CC and/or read incoming
- * messages
- */
- tcpc_run(port, evt);
-#else
- /* if TCPC has reset, then need to initialize it again */
- if (evt & PD_EVENT_TCPC_RESET) {
- reset_device_and_notify(port);
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- }
-
- if ((evt & PD_EVENT_TCPC_RESET) &&
- (pd[port].task_state != PD_STATE_DRP_AUTO_TOGGLE)) {
-#endif
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- if (pd[port].task_state == PD_STATE_SOFT_RESET) {
- enum tcpc_cc_voltage_status cc1, cc2;
-
- /*
- * Set the terminations to match our power
- * role.
- */
- tcpm_set_cc(port, pd[port].power_role ?
- TYPEC_CC_RP : TYPEC_CC_RD);
-
- /* Determine the polarity. */
- tcpm_get_cc(port, &cc1, &cc2);
- if (pd[port].power_role == PD_ROLE_SINK) {
- pd[port].polarity =
- get_snk_polarity(cc1, cc2);
- } else if (cc_is_snk_dbg_acc(cc1, cc2)) {
- pd[port].polarity =
- board_get_src_dts_polarity(
- port);
- } else {
- pd[port].polarity =
- get_src_polarity(cc1, cc2);
- }
- } else
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
- {
- /* Ensure CC termination is default */
- tcpm_set_cc(port, PD_ROLE_DEFAULT(port) ==
- PD_ROLE_SOURCE ? TYPEC_CC_RP :
- TYPEC_CC_RD);
- }
-
- /*
- * If we have a stable contract in the default role,
- * then simply update TCPC with some missing info
- * so that we can continue without resetting PD comms.
- * Otherwise, go to the default disconnected state
- * and force renegotiation.
- */
- if (pd[port].vdm_state == VDM_STATE_DONE && (
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- (PD_ROLE_DEFAULT(port) == PD_ROLE_SINK &&
- pd[port].task_state == PD_STATE_SNK_READY) ||
- (pd[port].task_state == PD_STATE_SOFT_RESET) ||
-#endif
- (PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE &&
- pd[port].task_state == PD_STATE_SRC_READY))) {
- pd_set_polarity(port, pd[port].polarity);
- tcpm_set_msg_header(port, pd[port].power_role,
- pd[port].data_role);
- tcpm_set_rx_enable(port, 1);
- } else {
- /* Ensure state variables are at default */
- pd_set_power_role(port, PD_ROLE_DEFAULT(port));
- pd[port].vdm_state = VDM_STATE_DONE;
- set_state(port, PD_DEFAULT_STATE(port));
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- pd_update_dual_role_config(port);
-#endif
- }
- }
-#endif
-
-#ifdef CONFIG_USBC_PPC
- /*
- * TODO: Useful for non-PPC cases as well, but only needed
- * for PPC cases right now. Revisit later.
- */
- if (evt & PD_EVENT_SEND_HARD_RESET)
- set_state(port, PD_STATE_HARD_RESET_SEND);
-#endif /* defined(CONFIG_USBC_PPC) */
-
- if (evt & PD_EVENT_RX_HARD_RESET)
- pd_execute_hard_reset(port);
-
- /* process any potential incoming message */
- incoming_packet = tcpm_has_pending_message(port);
- if (incoming_packet) {
- /* Dequeue and consume duplicate message ID. */
- if (tcpm_dequeue_message(port, payload, &head) ==
- EC_SUCCESS
- && !consume_repeat_message(port, head)
- )
- handle_request(port, head, payload);
-
- /* Check if there are any more messages */
- if (tcpm_has_pending_message(port))
- task_set_event(PD_PORT_TO_TASK_ID(port),
- TASK_EVENT_WAKE);
- }
-
- if (pd[port].req_suspend_state)
- set_state(port, PD_STATE_SUSPENDED);
-
- /* if nothing to do, verify the state of the world in 500ms */
- this_state = pd[port].task_state;
- timeout = 500*MSEC;
- switch (this_state) {
- case PD_STATE_DISABLED:
- /* Nothing to do */
- break;
- case PD_STATE_SRC_DISCONNECTED:
- timeout = 10*MSEC;
- pd_set_src_caps(port, 0, NULL);
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /*
- * If SW decided we should be in a low power state and
- * the CC lines did not change, then don't talk with the
- * TCPC otherwise we might wake it up.
- */
- if (pd[port].flags & PD_FLAGS_LPM_REQUESTED &&
- !(evt & PD_EVENT_CC))
- break;
-#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */
-
- tcpm_get_cc(port, &cc1, &cc2);
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- /*
- * Attempt TCPC auto DRP toggle if it is
- * not already auto toggling and not try.src
- */
- if (auto_toggle_supported &&
- !(pd[port].flags & PD_FLAGS_TCPC_DRP_TOGGLE) &&
- !is_try_src(port) &&
- cc_is_open(cc1, cc2)) {
- set_state(port, PD_STATE_DRP_AUTO_TOGGLE);
- timeout = 2*MSEC;
- break;
- }
-#endif
- /*
- * Transition to DEBOUNCE if we detect appropriate
- * signals
- *
- * (from 4.5.2.2.10.2 Exiting from Try.SRC State)
- * If try_src -and-
- * have only one Rd (not both) => DEBOUNCE
- *
- * (from 4.5.2.2.7.2 Exiting from Unattached.SRC State)
- * If not try_src -and-
- * have at least one Rd => DEBOUNCE -or-
- * have audio access => DEBOUNCE
- *
- * try_src should not exit if both pins are Rd
- */
- if ((is_try_src(port) && cc_is_only_one_rd(cc1, cc2)) ||
- (!is_try_src(port) &&
- (cc_is_at_least_one_rd(cc1, cc2) ||
- cc_is_audio_acc(cc1, cc2)))) {
-#ifdef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP
- /* Enable VBUS */
- if (pd_set_power_supply_ready(port))
- break;
-#endif
- pd[port].cc_state = PD_CC_NONE;
- set_state(port,
- PD_STATE_SRC_DISCONNECTED_DEBOUNCE);
- break;
- }
-#if defined(CONFIG_USB_PD_DUAL_ROLE)
- now = get_time();
- /*
- * Try.SRC state is embedded here. The port
- * shall transition to TryWait.SNK after
- * tDRPTry (PD_T_DRP_TRY) and Vbus is within
- * vSafe0V, or after tTryTimeout
- * (PD_T_TRY_TIMEOUT). Otherwise we should stay
- * within Try.SRC (break).
- */
- if (is_try_src(port)) {
- if (now.val < pd[port].try_src_marker) {
- break;
- } else if (now.val < pd[port].try_timeout) {
- if (pd_is_vbus_present(port))
- break;
- }
-
- /*
- * Transition to TryWait.SNK now, so set
- * state and update src marker time.
- */
- set_state(port, PD_STATE_SNK_DISCONNECTED);
- pd_set_power_role(port, PD_ROLE_SINK);
- tcpm_set_cc(port, TYPEC_CC_RD);
- pd[port].try_src_marker =
- get_time().val + PD_T_DEBOUNCE;
- timeout = 2 * MSEC;
- break;
- }
-
- /*
- * If Try.SRC state is not active, then handle
- * the normal DRP toggle from SRC->SNK.
- */
- if (now.val < next_role_swap ||
- drp_state[port] == PD_DRP_FORCE_SOURCE ||
- drp_state[port] == PD_DRP_FREEZE)
- break;
-
- /*
- * Transition to SNK now, so set state and
- * update next role swap time.
- */
- set_state(port, PD_STATE_SNK_DISCONNECTED);
- pd_set_power_role(port, PD_ROLE_SINK);
- tcpm_set_cc(port, TYPEC_CC_RD);
- next_role_swap = get_time().val + PD_T_DRP_SNK;
- /* Swap states quickly */
- timeout = 2 * MSEC;
-#endif
- break;
- case PD_STATE_SRC_DISCONNECTED_DEBOUNCE:
- timeout = 20*MSEC;
- tcpm_get_cc(port, &cc1, &cc2);
-
- if (cc_is_snk_dbg_acc(cc1, cc2)) {
- /* Debug accessory */
- new_cc_state = PD_CC_UFP_DEBUG_ACC;
- } else if (cc_is_at_least_one_rd(cc1, cc2)) {
- /* UFP attached */
- new_cc_state = PD_CC_UFP_ATTACHED;
- } else if (cc_is_audio_acc(cc1, cc2)) {
- /* Audio accessory */
- new_cc_state = PD_CC_UFP_AUDIO_ACC;
- } else {
- /* No UFP */
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- timeout = 5*MSEC;
- break;
- }
-
- /* Set debounce timer */
- if (new_cc_state != pd[port].cc_state) {
- pd[port].cc_debounce =
- get_time().val +
- (is_try_src(port) ? PD_T_DEBOUNCE
- : PD_T_CC_DEBOUNCE);
- pd[port].cc_state = new_cc_state;
- break;
- }
-
- /* Debounce the cc state */
- if (get_time().val < pd[port].cc_debounce)
- break;
-
- /* Debounce complete */
- if (IS_ENABLED(CONFIG_COMMON_RUNTIME))
- hook_notify(HOOK_USB_PD_CONNECT);
-
-#ifdef CONFIG_USBC_PPC
- /*
- * If the port is latched off, just continue to
- * monitor for a detach.
- */
- if (usbc_ocp_is_port_latched_off(port))
- break;
-#endif /* CONFIG_USBC_PPC */
-
- /* UFP is attached */
- if (new_cc_state == PD_CC_UFP_ATTACHED ||
- new_cc_state == PD_CC_UFP_DEBUG_ACC) {
-#ifdef CONFIG_USBC_PPC
- /* Inform PPC that a sink is connected. */
- ppc_dev_is_connected(port, PPC_DEV_SNK);
-#endif /* CONFIG_USBC_PPC */
- if (IS_ENABLED(CONFIG_USBC_OCP))
- usbc_ocp_snk_is_connected(port, true);
- if (new_cc_state == PD_CC_UFP_DEBUG_ACC) {
- pd[port].polarity =
- board_get_src_dts_polarity(
- port);
- } else {
- pd[port].polarity =
- get_src_polarity(cc1, cc2);
- }
- pd_set_polarity(port, pd[port].polarity);
-
- /* initial data role for source is DFP */
- pd_set_data_role(port, PD_ROLE_DFP);
-
- /* Enable Auto Discharge Disconnect */
- tcpm_enable_auto_discharge_disconnect(port, 1);
-
- if (new_cc_state == PD_CC_UFP_DEBUG_ACC)
- pd[port].flags |=
- PD_FLAGS_TS_DTS_PARTNER;
-
-#ifdef CONFIG_USBC_VCONN
- /*
- * Do not source Vconn when debug accessory is
- * detected. Section 4.5.2.2.17.1 in USB spec
- * v1-3
- */
- if (new_cc_state != PD_CC_UFP_DEBUG_ACC) {
- /*
- * Start sourcing Vconn before Vbus to
- * ensure we are within USB Type-C
- * Spec 1.3 tVconnON.
- */
- set_vconn(port, 1);
- pd_set_vconn_role(port,
- PD_ROLE_VCONN_ON);
- }
-#endif
-
-#ifndef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP
- /* Enable VBUS */
- if (pd_set_power_supply_ready(port)) {
-#ifdef CONFIG_USBC_VCONN
- /* Stop sourcing Vconn if Vbus failed */
- set_vconn(port, 0);
- pd_set_vconn_role(port,
- PD_ROLE_VCONN_OFF);
-#endif /* CONFIG_USBC_VCONN */
-#ifdef CONFIG_USBC_SS_MUX
- usb_mux_set(port, USB_PD_MUX_NONE,
- USB_SWITCH_DISCONNECT,
- pd[port].polarity);
-#endif /* CONFIG_USBC_SS_MUX */
- break;
- }
- /*
- * Set correct Rp value determined during
- * pd_set_power_supply_ready. This should be
- * safe because Vconn is being sourced,
- * preventing incorrect CCD detection.
- */
- tcpm_set_cc(port, TYPEC_CC_RP);
-#endif /* CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP */
- /* If PD comm is enabled, enable TCPC RX */
- if (pd_comm_is_enabled(port))
- tcpm_set_rx_enable(port, 1);
-
- pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE |
- PD_FLAGS_CHECK_DR_ROLE;
- hard_reset_count = 0;
- timeout = 5*MSEC;
-
- set_state(port, PD_STATE_SRC_STARTUP);
- }
- /*
- * AUDIO_ACC will remain in this state indefinitely
- * until disconnect.
- */
- break;
- case PD_STATE_SRC_HARD_RESET_RECOVER:
- /* Do not continue until hard reset recovery time */
- if (get_time().val < pd[port].src_recover) {
- timeout = 50*MSEC;
- break;
- }
-
-#ifdef CONFIG_USBC_VCONN
- /*
- * Start sourcing Vconn again and set the flag, in case
- * it was 0 due to a previous swap
- */
- set_vconn(port, 1);
- pd_set_vconn_role(port, PD_ROLE_VCONN_ON);
-#endif
-
- /* Enable VBUS */
- timeout = 10*MSEC;
- if (pd_set_power_supply_ready(port)) {
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- break;
- }
-#if defined(CONFIG_USB_PD_TCPM_TCPCI) || defined(CONFIG_USB_PD_TCPM_STUB)
- /*
- * After transmitting hard reset, TCPM writes
- * to RECEIVE_DETECT register to enable
- * PD message passing.
- */
- if (pd_comm_is_enabled(port))
- tcpm_set_rx_enable(port, 1);
-#endif /* CONFIG_USB_PD_TCPM_TCPCI || CONFIG_USB_PD_TCPM_STUB */
-
- pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE |
- PD_FLAGS_CHECK_DR_ROLE;
- set_state(port, PD_STATE_SRC_STARTUP);
- break;
- case PD_STATE_SRC_STARTUP:
- /* Reset cable attributes and flags */
- reset_pd_cable(port);
- /* Wait for power source to enable */
- if (pd[port].last_state != pd[port].task_state) {
- pd[port].flags |= PD_FLAGS_CHECK_IDENTITY;
- /* reset various counters */
- caps_count = 0;
- pd[port].msg_id = 0;
- snk_cap_count = 0;
- set_state_timeout(
- port,
-#ifdef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP
- /*
- * delay for power supply to start up.
- * subtract out debounce time if coming
- * from debounce state since vbus is
- * on during debounce.
- */
- get_time().val +
- PD_POWER_SUPPLY_TURN_ON_DELAY -
- (pd[port].last_state ==
- PD_STATE_SRC_DISCONNECTED_DEBOUNCE
- ? PD_T_CC_DEBOUNCE : 0),
-#else
- get_time().val +
- PD_POWER_SUPPLY_TURN_ON_DELAY,
-#endif
- PD_STATE_SRC_DISCOVERY);
- }
- break;
- case PD_STATE_SRC_DISCOVERY:
- now = get_time();
- if (pd[port].last_state != pd[port].task_state) {
- caps_count = 0;
- next_src_cap = now.val;
- /*
- * If we have had PD connection with this port
- * partner, then start NoResponseTimer.
- */
- if (pd_capable(port))
- set_state_timeout(port,
- get_time().val +
- PD_T_NO_RESPONSE,
- hard_reset_count <
- PD_HARD_RESET_COUNT ?
- PD_STATE_HARD_RESET_SEND :
- PD_STATE_SRC_DISCONNECTED);
- }
-
- /* Send source cap some minimum number of times */
- if (caps_count < PD_CAPS_COUNT &&
- next_src_cap <= now.val) {
- /* Query capabilities of the other side */
- res = send_source_cap(port, AMS_START);
- /* packet was acked => PD capable device) */
- if (res >= 0) {
- set_state(port,
- PD_STATE_SRC_NEGOCIATE);
- timeout = 10*MSEC;
- hard_reset_count = 0;
- caps_count = 0;
- /* Port partner is PD capable */
- pd[port].flags |=
- PD_FLAGS_PREVIOUS_PD_CONN;
- } else { /* failed, retry later */
- timeout = PD_T_SEND_SOURCE_CAP;
- next_src_cap = now.val +
- PD_T_SEND_SOURCE_CAP;
- caps_count++;
- }
- } else if (caps_count < PD_CAPS_COUNT) {
- timeout = next_src_cap - now.val;
- }
- break;
- case PD_STATE_SRC_NEGOCIATE:
- /* wait for a "Request" message */
- if (pd[port].last_state != pd[port].task_state)
- set_state_timeout(port,
- get_time().val +
- PD_T_SENDER_RESPONSE,
- PD_STATE_HARD_RESET_SEND);
- break;
- case PD_STATE_SRC_ACCEPTED:
- /* Accept sent, wait for enabling the new voltage */
- if (pd[port].last_state != pd[port].task_state)
- set_state_timeout(
- port,
- get_time().val +
- PD_T_SINK_TRANSITION,
- PD_STATE_SRC_POWERED);
- break;
- case PD_STATE_SRC_POWERED:
- /* Switch to the new requested voltage */
- if (pd[port].last_state != pd[port].task_state) {
- pd[port].flags |= PD_FLAGS_CHECK_VCONN_STATE;
- pd_transition_voltage(pd[port].requested_idx);
- set_state_timeout(
- port,
- get_time().val +
- PD_POWER_SUPPLY_TURN_ON_DELAY,
- PD_STATE_SRC_TRANSITION);
- }
- break;
- case PD_STATE_SRC_TRANSITION:
- /* the voltage output is good, notify the source */
- res = send_control(port, PD_CTRL_PS_RDY);
- if (res >= 0) {
- timeout = 10*MSEC;
-
- /*
- * Give the sink some time to send any messages
- * before we may send messages of our own. Add
- * some jitter of up to ~192ms, to prevent
- * multiple collisions. This delay also allows
- * the sink device to request power role swap
- * and allow the the accept message to be sent
- * prior to CMD_DISCOVER_IDENT being sent in the
- * SRC_READY state.
- */
- pd[port].ready_state_holdoff_timer =
- get_time().val + SRC_READY_HOLD_OFF_US
- + (get_time().le.lo & 0xf) * 12 * MSEC;
-
- /* it's time to ping regularly the sink */
- set_state(port, PD_STATE_SRC_READY);
- } else {
- /* The sink did not ack, cut the power... */
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- }
- break;
- case PD_STATE_SRC_READY:
- timeout = PD_T_SOURCE_ACTIVITY;
-
- /*
- * Don't send any traffic yet until our holdoff timer
- * has expired. Some devices are chatty once we reach
- * the SRC_READY state and we may end up in a collision
- * of messages if we try to immediately send our
- * interrogations.
- */
- if (get_time().val <=
- pd[port].ready_state_holdoff_timer)
- break;
-
- /*
- * Don't send any PD traffic if we woke up due to
- * incoming packet or if VDO response pending to avoid
- * collisions.
- */
- if (incoming_packet ||
- (pd[port].vdm_state == VDM_STATE_BUSY))
- break;
-
- /* Send updated source capabilities to our partner */
- if (pd[port].flags & PD_FLAGS_UPDATE_SRC_CAPS) {
- res = send_source_cap(port, AMS_START);
- if (res >= 0) {
- set_state(port,
- PD_STATE_SRC_NEGOCIATE);
- pd[port].flags &=
- ~PD_FLAGS_UPDATE_SRC_CAPS;
- }
- break;
- }
-
- /* Send get sink cap if haven't received it yet */
- if (!(pd[port].flags & PD_FLAGS_SNK_CAP_RECVD)) {
- if (++snk_cap_count <= PD_SNK_CAP_RETRIES) {
- /* Get sink cap to know if dual-role device */
- send_control(port, PD_CTRL_GET_SINK_CAP);
- set_state(port, PD_STATE_SRC_GET_SINK_CAP);
- break;
- } else if (debug_level >= 2 &&
- snk_cap_count == PD_SNK_CAP_RETRIES+1) {
- CPRINTF("C%d ERR SNK_CAP\n", port);
- }
- }
-
- /* Check power role policy, which may trigger a swap */
- if (pd[port].flags & PD_FLAGS_CHECK_PR_ROLE) {
- pd_check_pr_role(port, PD_ROLE_SOURCE,
- pd[port].flags);
- pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE;
- }
-
-
- /* Check data role policy, which may trigger a swap */
- if (pd[port].flags & PD_FLAGS_CHECK_DR_ROLE) {
- pd_check_dr_role(port, pd[port].data_role,
- pd[port].flags);
- pd[port].flags &= ~PD_FLAGS_CHECK_DR_ROLE;
- break;
- }
-
- /* Check for Vconn source, which may trigger a swap */
- if (pd[port].flags & PD_FLAGS_CHECK_VCONN_STATE) {
- /*
- * Ref: Section 2.6.1 of both
- * USB-PD Spec Revision 2.0, Version 1.3 &
- * USB-PD Spec Revision 3.0, Version 2.0
- * During Explicit contract the Sink can
- * initiate or receive a request an exchange
- * of VCONN Source.
- */
- pd_try_execute_vconn_swap(port,
- pd[port].flags);
- pd[port].flags &= ~PD_FLAGS_CHECK_VCONN_STATE;
- break;
- }
-
- /* Send discovery SVDMs last */
- if (pd[port].data_role == PD_ROLE_DFP &&
- (pd[port].flags & PD_FLAGS_CHECK_IDENTITY)) {
-#ifndef CONFIG_USB_PD_SIMPLE_DFP
- pd_send_vdm(port, USB_SID_PD,
- CMD_DISCOVER_IDENT, NULL, 0);
-#endif
- pd[port].flags &= ~PD_FLAGS_CHECK_IDENTITY;
- break;
- }
-
- /*
- * Enter_USB if port partner and cable are
- * USB4 compatible.
- */
- if (should_enter_usb4_mode(port)) {
- pd_send_enter_usb(port, &timeout);
- break;
- }
-
- if (!(pd[port].flags & PD_FLAGS_PING_ENABLED))
- break;
-
- /* Verify that the sink is alive */
- res = send_control(port, PD_CTRL_PING);
- if (res >= 0)
- break;
-
- /* Ping dropped. Try soft reset. */
- set_state(port, PD_STATE_SOFT_RESET);
- timeout = 10 * MSEC;
- break;
- case PD_STATE_SRC_GET_SINK_CAP:
- if (pd[port].last_state != pd[port].task_state)
- set_state_timeout(port,
- get_time().val +
- PD_T_SENDER_RESPONSE,
- PD_STATE_SRC_READY);
- break;
- case PD_STATE_DR_SWAP:
- if (pd[port].last_state != pd[port].task_state) {
- res = send_control(port, PD_CTRL_DR_SWAP);
- if (res < 0) {
- timeout = 10*MSEC;
- /*
- * If failed to get goodCRC, send
- * soft reset, otherwise ignore
- * failure.
- */
- set_state(port, res == -1 ?
- PD_STATE_SOFT_RESET :
- READY_RETURN_STATE(port));
- break;
- }
- /* Wait for accept or reject */
- set_state_timeout(port,
- get_time().val +
- PD_T_SENDER_RESPONSE,
- READY_RETURN_STATE(port));
- }
- break;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- case PD_STATE_SRC_SWAP_INIT:
- if (pd[port].last_state != pd[port].task_state) {
- res = send_control(port, PD_CTRL_PR_SWAP);
- if (res < 0) {
- timeout = 10*MSEC;
- /*
- * If failed to get goodCRC, send
- * soft reset, otherwise ignore
- * failure.
- */
- set_state(port, res == -1 ?
- PD_STATE_SOFT_RESET :
- PD_STATE_SRC_READY);
- break;
- }
- /* Wait for accept or reject */
- set_state_timeout(port,
- get_time().val +
- PD_T_SENDER_RESPONSE,
- PD_STATE_SRC_READY);
- }
- break;
- case PD_STATE_SRC_SWAP_SNK_DISABLE:
- /* Give time for sink to stop drawing current */
- if (pd[port].last_state != pd[port].task_state)
- set_state_timeout(port,
- get_time().val +
- PD_T_SINK_TRANSITION,
- PD_STATE_SRC_SWAP_SRC_DISABLE);
- break;
- case PD_STATE_SRC_SWAP_SRC_DISABLE:
- if (pd[port].last_state != pd[port].task_state) {
- /* Turn power off */
- pd_power_supply_reset(port);
-
- /*
- * Switch to Rd and swap roles to sink
- *
- * The reason we do this as early as possible is
- * to help prevent CC disconnection cases where
- * both partners are applying an Rp. Certain PD
- * stacks (e.g. qualcomm), reflexively apply
- * their Rp once VBUS falls beneath
- * ~3.67V. (b/77827528).
- */
- tcpm_set_cc(port, TYPEC_CC_RD);
- pd_set_power_role(port, PD_ROLE_SINK);
-
- /* Inform TCPC of power role update. */
- pd_update_roles(port);
-
- set_state_timeout(port,
- get_time().val +
- PD_POWER_SUPPLY_TURN_OFF_DELAY,
- PD_STATE_SRC_SWAP_STANDBY);
- }
- break;
- case PD_STATE_SRC_SWAP_STANDBY:
- /* Send PS_RDY to let sink know our power is off */
- if (pd[port].last_state != pd[port].task_state) {
- /* Send PS_RDY */
- res = send_control(port, PD_CTRL_PS_RDY);
- if (res < 0) {
- timeout = 10*MSEC;
- set_state(port,
- PD_STATE_SRC_DISCONNECTED);
- break;
- }
- /* Wait for PS_RDY from new source */
- set_state_timeout(port,
- get_time().val +
- PD_T_PS_SOURCE_ON,
- PD_STATE_SNK_DISCONNECTED);
- }
- break;
- case PD_STATE_SUSPENDED: {
-#ifndef CONFIG_USB_PD_TCPC
- int rstatus;
-#endif
- tcpc_prints("suspended!", port);
- pd[port].req_suspend_state = 0;
-#ifdef CONFIG_USB_PD_TCPC
- pd_rx_disable_monitoring(port);
- pd_hw_release(port);
- pd_power_supply_reset(port);
-#else
- pd_power_supply_reset(port);
-#ifdef CONFIG_USBC_VCONN
- set_vconn(port, 0);
-#endif
- rstatus = tcpm_release(port);
- if (rstatus != 0 && rstatus != EC_ERROR_UNIMPLEMENTED)
- tcpc_prints("release failed!", port);
-#endif
- /* Drain any outstanding software message queues. */
- tcpm_clear_pending_messages(port);
-
- /* Wait for resume */
- while (pd[port].task_state == PD_STATE_SUSPENDED) {
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- int evt = task_wait_event(-1);
-
- if (evt & PD_EVENT_SYSJUMP)
- /* Nothing to do for sysjump prep */
- notify_sysjump_ready();
-#else
- task_wait_event(-1);
-#endif
- }
-#ifdef CONFIG_USB_PD_TCPC
- pd_hw_init(port, PD_ROLE_DEFAULT(port));
- tcpc_prints("resumed!", port);
-#else
- if (rstatus != EC_ERROR_UNIMPLEMENTED &&
- pd_restart_tcpc(port) != 0) {
- /* stay in PD_STATE_SUSPENDED */
- tcpc_prints("restart failed!", port);
- break;
- }
- /* Set the CC termination and state back to default */
- tcpm_set_cc(port,
- PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE ?
- TYPEC_CC_RP :
- TYPEC_CC_RD);
- set_state(port, PD_DEFAULT_STATE(port));
- tcpc_prints("resumed!", port);
-#endif
- break;
- }
- case PD_STATE_SNK_DISCONNECTED:
-#ifdef CONFIG_USB_PD_LOW_POWER
- timeout = (drp_state[port] !=
- PD_DRP_TOGGLE_ON ? SECOND : 10*MSEC);
-#else
- timeout = 10*MSEC;
-#endif
- pd_set_src_caps(port, 0, NULL);
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /*
- * If SW decided we should be in a low power state and
- * the CC lines did not change, then don't talk with the
- * TCPC otherwise we might wake it up.
- */
- if (pd[port].flags & PD_FLAGS_LPM_REQUESTED &&
- !(evt & PD_EVENT_CC))
- break;
-#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */
-
- tcpm_get_cc(port, &cc1, &cc2);
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- /*
- * Attempt TCPC auto DRP toggle if it is not already
- * auto toggling and not try.src, and dual role toggling
- * is allowed.
- */
- if (auto_toggle_supported &&
- !(pd[port].flags & PD_FLAGS_TCPC_DRP_TOGGLE) &&
- !is_try_src(port) &&
- cc_is_open(cc1, cc2) &&
- (drp_state[port] == PD_DRP_TOGGLE_ON)) {
- set_state(port, PD_STATE_DRP_AUTO_TOGGLE);
- timeout = 2*MSEC;
- break;
- }
-#endif
-
- /* Source connection monitoring */
- if (!cc_is_open(cc1, cc2)) {
- pd[port].cc_state = PD_CC_NONE;
- hard_reset_count = 0;
- new_cc_state = PD_CC_NONE;
- pd[port].cc_debounce = get_time().val +
- PD_T_CC_DEBOUNCE;
- set_state(port,
- PD_STATE_SNK_DISCONNECTED_DEBOUNCE);
- timeout = 10*MSEC;
- break;
- }
-
- /*
- * If Try.SRC is active and failed to detect a SNK,
- * then it transitions to TryWait.SNK. Need to prevent
- * normal dual role toggle until tDRPTryWait timer
- * expires.
- */
- if (pd[port].flags & PD_FLAGS_TRY_SRC) {
- if (get_time().val > pd[port].try_src_marker)
- pd[port].flags &= ~PD_FLAGS_TRY_SRC;
- break;
- }
-
- /* If no source detected, check for role toggle. */
- if (drp_state[port] == PD_DRP_TOGGLE_ON &&
- get_time().val >= next_role_swap) {
- /* Swap roles to source */
- pd_set_power_role(port, PD_ROLE_SOURCE);
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- tcpm_set_cc(port, TYPEC_CC_RP);
- next_role_swap = get_time().val + PD_T_DRP_SRC;
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /*
- * Clear low power mode flag as we are swapping
- * states quickly.
- */
- pd[port].flags &= ~PD_FLAGS_LPM_REQUESTED;
-#endif
-
- /* Swap states quickly */
- timeout = 2*MSEC;
- break;
- }
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /*
- * If we are remaining in the SNK_DISCONNECTED state,
- * let's go into low power mode and wait for a change on
- * CC status.
- */
- pd[port].flags |= PD_FLAGS_LPM_REQUESTED;
-#endif/* CONFIG_USB_PD_TCPC_LOW_POWER */
- break;
-
- case PD_STATE_SNK_DISCONNECTED_DEBOUNCE:
- tcpm_get_cc(port, &cc1, &cc2);
-
- if (cc_is_rp(cc1) && cc_is_rp(cc2)) {
- /* Debug accessory */
- new_cc_state = PD_CC_DFP_DEBUG_ACC;
- } else if (cc_is_rp(cc1) || cc_is_rp(cc2)) {
- new_cc_state = PD_CC_DFP_ATTACHED;
- } else {
- /* No connection any more */
- set_state(port, PD_STATE_SNK_DISCONNECTED);
- timeout = 5*MSEC;
- break;
- }
-
- timeout = 20*MSEC;
-
- /* Debounce the cc state */
- if (new_cc_state != pd[port].cc_state) {
- pd[port].cc_debounce = get_time().val +
- PD_T_CC_DEBOUNCE;
- pd[port].cc_state = new_cc_state;
- break;
- }
- /* Wait for CC debounce and VBUS present */
- if (get_time().val < pd[port].cc_debounce ||
- !pd_is_vbus_present(port))
- break;
-
- if (pd_try_src_enable &&
- !(pd[port].flags & PD_FLAGS_TRY_SRC)) {
- /*
- * If TRY_SRC is enabled, but not active,
- * then force attempt to connect as source.
- */
- pd[port].try_src_marker = get_time().val
- + PD_T_DRP_TRY;
- pd[port].try_timeout = get_time().val
- + PD_T_TRY_TIMEOUT;
- /* Swap roles to source */
- pd_set_power_role(port, PD_ROLE_SOURCE);
- tcpm_set_cc(port, TYPEC_CC_RP);
- timeout = 2*MSEC;
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- /* Set flag after the state change */
- pd[port].flags |= PD_FLAGS_TRY_SRC;
- break;
- }
-
- /* We are attached */
- if (IS_ENABLED(CONFIG_COMMON_RUNTIME))
- hook_notify(HOOK_USB_PD_CONNECT);
- pd[port].polarity = get_snk_polarity(cc1, cc2);
- pd_set_polarity(port, pd[port].polarity);
- /* reset message ID on connection */
- pd[port].msg_id = 0;
- /* initial data role for sink is UFP */
- pd_set_data_role(port, PD_ROLE_UFP);
- /* Enable Auto Discharge Disconnect */
- tcpm_enable_auto_discharge_disconnect(port, 1);
-#if defined(CONFIG_CHARGE_MANAGER)
- typec_curr = usb_get_typec_current_limit(
- pd[port].polarity, cc1, cc2);
- typec_set_input_current_limit(
- port, typec_curr, TYPE_C_VOLTAGE);
-#endif
-
-#ifdef CONFIG_USBC_PPC
- /* Inform PPC that a source is connected. */
- ppc_dev_is_connected(port, PPC_DEV_SRC);
-#endif /* CONFIG_USBC_PPC */
- if (IS_ENABLED(CONFIG_USBC_OCP))
- usbc_ocp_snk_is_connected(port, false);
-
- /* If PD comm is enabled, enable TCPC RX */
- if (pd_comm_is_enabled(port))
- tcpm_set_rx_enable(port, 1);
-
- /* DFP is attached */
- if (new_cc_state == PD_CC_DFP_ATTACHED ||
- new_cc_state == PD_CC_DFP_DEBUG_ACC) {
- pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE |
- PD_FLAGS_CHECK_DR_ROLE |
- PD_FLAGS_CHECK_IDENTITY;
- /* Reset cable attributes and flags */
- reset_pd_cable(port);
-
- if (new_cc_state == PD_CC_DFP_DEBUG_ACC)
- pd[port].flags |=
- PD_FLAGS_TS_DTS_PARTNER;
- set_state(port, PD_STATE_SNK_DISCOVERY);
- timeout = 10*MSEC;
- hook_call_deferred(
- &pd_usb_billboard_deferred_data,
- PD_T_AME);
- }
- break;
- case PD_STATE_SNK_HARD_RESET_RECOVER:
- if (pd[port].last_state != pd[port].task_state)
- pd[port].flags |= PD_FLAGS_CHECK_IDENTITY;
-
- if (get_usb_pd_vbus_detect() ==
- USB_PD_VBUS_DETECT_NONE) {
- /*
- * Can't measure vbus state so this is the
- * maximum recovery time for the source.
- */
- if (pd[port].last_state != pd[port].task_state)
- set_state_timeout(port, get_time().val +
- PD_T_SAFE_0V +
- PD_T_SRC_RECOVER_MAX +
- PD_T_SRC_TURN_ON,
- PD_STATE_SNK_DISCONNECTED);
- } else {
-#ifndef CONFIG_USB_PD_VBUS_DETECT_NONE
- /* Wait for VBUS to go low and then high*/
- if (pd[port].last_state !=
- pd[port].task_state) {
- snk_hard_reset_vbus_off = 0;
- set_state_timeout(port,
- get_time().val +
- PD_T_SAFE_0V,
- hard_reset_count <
- PD_HARD_RESET_COUNT ?
- PD_STATE_HARD_RESET_SEND :
- PD_STATE_SNK_DISCOVERY);
- }
-
- if (!pd_is_vbus_present(port) &&
- !snk_hard_reset_vbus_off) {
- /* VBUS has gone low, reset timeout */
- snk_hard_reset_vbus_off = 1;
- set_state_timeout(port,
- get_time().val +
- PD_T_SRC_RECOVER_MAX +
- PD_T_SRC_TURN_ON,
- PD_STATE_SNK_DISCONNECTED);
- }
- if (pd_is_vbus_present(port) &&
- snk_hard_reset_vbus_off) {
- /* VBUS went high again */
- set_state(port, PD_STATE_SNK_DISCOVERY);
- timeout = 10*MSEC;
- }
-
- /*
- * Don't need to set timeout because VBUS
- * changing will trigger an interrupt and
- * wake us up.
- */
-#endif
- }
- break;
- case PD_STATE_SNK_DISCOVERY:
- /* Wait for source cap expired only if we are enabled */
- if ((pd[port].last_state != pd[port].task_state)
- && pd_comm_is_enabled(port)) {
-#if defined(CONFIG_USB_PD_TCPM_TCPCI) || defined(CONFIG_USB_PD_TCPM_STUB)
- /*
- * If we come from hard reset recover state,
- * then we can process the source capabilities
- * form partner now, so enable PHY layer
- * receiving function.
- */
- if (pd[port].last_state ==
- PD_STATE_SNK_HARD_RESET_RECOVER)
- tcpm_set_rx_enable(port, 1);
-#endif /* CONFIG_USB_PD_TCPM_TCPCI || CONFIG_USB_PD_TCPM_STUB */
-#ifdef CONFIG_USB_PD_RESET_MIN_BATT_SOC
- /*
- * If the battery has not met a configured safe
- * level for hard resets, refrain from starting
- * reset timers as a hard reset could brown out
- * the board. Note this may mean that
- * high-power chargers will stay at 15W until a
- * reset is sent, depending on boot timing.
- */
- int batt_soc = usb_get_battery_soc();
-
- if (batt_soc < CONFIG_USB_PD_RESET_MIN_BATT_SOC ||
- battery_get_disconnect_state() !=
- BATTERY_NOT_DISCONNECTED)
- pd[port].flags |=
- PD_FLAGS_SNK_WAITING_BATT;
- else
- pd[port].flags &=
- ~PD_FLAGS_SNK_WAITING_BATT;
-#endif
-
- if (pd[port].flags &
- PD_FLAGS_SNK_WAITING_BATT) {
-#ifdef CONFIG_CHARGE_MANAGER
- /*
- * Configure this port as dedicated for
- * now, so it won't be de-selected by
- * the charge manager leaving safe mode.
- */
- charge_manager_update_dualrole(port,
- CAP_DEDICATED);
-#endif
- CPRINTS("C%d: Battery low. "
- "Hold reset timer", port);
- /*
- * If VBUS has never been low, and we timeout
- * waiting for source cap, try a soft reset
- * first, in case we were already in a stable
- * contract before this boot.
- */
- } else if (pd[port].flags &
- PD_FLAGS_VBUS_NEVER_LOW) {
- set_state_timeout(port,
- get_time().val +
- PD_T_SINK_WAIT_CAP,
- PD_STATE_SOFT_RESET);
- /*
- * If we haven't passed hard reset counter,
- * start SinkWaitCapTimer, otherwise start
- * NoResponseTimer.
- */
- } else if (hard_reset_count <
- PD_HARD_RESET_COUNT) {
- set_state_timeout(port,
- get_time().val +
- PD_T_SINK_WAIT_CAP,
- PD_STATE_HARD_RESET_SEND);
- } else if (pd_capable(port)) {
- /* ErrorRecovery */
- set_state_timeout(port,
- get_time().val +
- PD_T_NO_RESPONSE,
- PD_STATE_SNK_DISCONNECTED);
- }
-#if defined(CONFIG_CHARGE_MANAGER)
- /*
- * If we didn't come from disconnected, must
- * have come from some path that did not set
- * typec current limit. So, set to 0 so that
- * we guarantee this is revised below.
- */
- if (pd[port].last_state !=
- PD_STATE_SNK_DISCONNECTED_DEBOUNCE)
- typec_curr = 0;
-#endif
- }
-
-#if defined(CONFIG_CHARGE_MANAGER)
- timeout = PD_T_SINK_ADJ - PD_T_DEBOUNCE;
-
- /* Check if CC pull-up has changed */
- tcpm_get_cc(port, &cc1, &cc2);
- if (typec_curr != usb_get_typec_current_limit(
- pd[port].polarity, cc1, cc2)) {
- /* debounce signal by requiring two reads */
- if (typec_curr_change) {
- /* set new input current limit */
- typec_curr =
- usb_get_typec_current_limit(
- pd[port].polarity,
- cc1, cc2);
- typec_set_input_current_limit(
- port, typec_curr, TYPE_C_VOLTAGE);
- } else {
- /* delay for debounce */
- timeout = PD_T_DEBOUNCE;
- }
- typec_curr_change = !typec_curr_change;
- } else {
- typec_curr_change = 0;
- }
-#endif
- break;
- case PD_STATE_SNK_REQUESTED:
- /* Wait for ACCEPT or REJECT */
- if (pd[port].last_state != pd[port].task_state) {
- pd[port].flags |= PD_FLAGS_CHECK_VCONN_STATE;
- hard_reset_count = 0;
- set_state_timeout(port,
- get_time().val +
- PD_T_SENDER_RESPONSE,
- PD_STATE_HARD_RESET_SEND);
- }
- break;
- case PD_STATE_SNK_TRANSITION:
- /* Wait for PS_RDY */
- if (pd[port].last_state != pd[port].task_state)
- set_state_timeout(port,
- get_time().val +
- PD_T_PS_TRANSITION,
- PD_STATE_HARD_RESET_SEND);
- break;
- case PD_STATE_SNK_READY:
- timeout = 20*MSEC;
-
- /*
- * Don't send any traffic yet until our holdoff timer
- * has expired. Some devices are chatty once we reach
- * the SNK_READY state and we may end up in a collision
- * of messages if we try to immediately send our
- * interrogations.
- */
- if (get_time().val <=
- pd[port].ready_state_holdoff_timer)
- break;
-
- /*
- * Don't send any PD traffic if we woke up due to
- * incoming packet or if VDO response pending to avoid
- * collisions.
- */
- if (incoming_packet ||
- (pd[port].vdm_state == VDM_STATE_BUSY))
- break;
-
- /* Check for new power to request */
- if (pd[port].new_power_request) {
- if (pd_send_request_msg(port, 0) != EC_SUCCESS)
- set_state(port, PD_STATE_SOFT_RESET);
- break;
- }
-
- /* Check power role policy, which may trigger a swap */
- if (pd[port].flags & PD_FLAGS_CHECK_PR_ROLE) {
- pd_check_pr_role(port, PD_ROLE_SINK,
- pd[port].flags);
- pd[port].flags &= ~PD_FLAGS_CHECK_PR_ROLE;
- break;
- }
-
- /* Check data role policy, which may trigger a swap */
- if (pd[port].flags & PD_FLAGS_CHECK_DR_ROLE) {
- pd_check_dr_role(port, pd[port].data_role,
- pd[port].flags);
- pd[port].flags &= ~PD_FLAGS_CHECK_DR_ROLE;
- break;
- }
-
- /* Check for Vconn source, which may trigger a swap */
- if (pd[port].flags & PD_FLAGS_CHECK_VCONN_STATE) {
- /*
- * Ref: Section 2.6.2 of both
- * USB-PD Spec Revision 2.0, Version 1.3 &
- * USB-PD Spec Revision 3.0, Version 2.0
- * During Explicit contract the Sink can
- * initiate or receive a request an exchange
- * of VCONN Source.
- */
- pd_try_execute_vconn_swap(port,
- pd[port].flags);
- pd[port].flags &= ~PD_FLAGS_CHECK_VCONN_STATE;
- break;
- }
-
- /* If DFP, send discovery SVDMs */
- if (pd[port].data_role == PD_ROLE_DFP &&
- (pd[port].flags & PD_FLAGS_CHECK_IDENTITY)) {
- pd_send_vdm(port, USB_SID_PD,
- CMD_DISCOVER_IDENT, NULL, 0);
- pd[port].flags &= ~PD_FLAGS_CHECK_IDENTITY;
- break;
- }
-
- /*
- * Enter_USB if port partner and cable are
- * USB4 compatible.
- */
- if (should_enter_usb4_mode(port)) {
- pd_send_enter_usb(port, &timeout);
- break;
- }
-
- /* Sent all messages, don't need to wake very often */
- timeout = 200*MSEC;
- break;
- case PD_STATE_SNK_SWAP_INIT:
- if (pd[port].last_state != pd[port].task_state) {
- res = send_control(port, PD_CTRL_PR_SWAP);
- if (res < 0) {
- timeout = 10*MSEC;
- /*
- * If failed to get goodCRC, send
- * soft reset, otherwise ignore
- * failure.
- */
- set_state(port, res == -1 ?
- PD_STATE_SOFT_RESET :
- PD_STATE_SNK_READY);
- break;
- }
- /* Wait for accept or reject */
- set_state_timeout(port,
- get_time().val +
- PD_T_SENDER_RESPONSE,
- PD_STATE_SNK_READY);
- }
- break;
- case PD_STATE_SNK_SWAP_SNK_DISABLE:
- /* Stop drawing power */
- pd_set_input_current_limit(port, 0, 0);
-#ifdef CONFIG_CHARGE_MANAGER
- typec_set_input_current_limit(port, 0, 0);
- charge_manager_set_ceil(port,
- CEIL_REQUESTOR_PD,
- CHARGE_CEIL_NONE);
-#endif
- set_state(port, PD_STATE_SNK_SWAP_SRC_DISABLE);
- timeout = 10*MSEC;
- break;
- case PD_STATE_SNK_SWAP_SRC_DISABLE:
- /* Wait for PS_RDY */
- if (pd[port].last_state != pd[port].task_state)
- set_state_timeout(port,
- get_time().val +
- PD_T_PS_SOURCE_OFF,
- PD_STATE_HARD_RESET_SEND);
- break;
- case PD_STATE_SNK_SWAP_STANDBY:
- if (pd[port].last_state != pd[port].task_state) {
- /* Switch to Rp and enable power supply. */
- tcpm_set_cc(port, TYPEC_CC_RP);
- if (pd_set_power_supply_ready(port)) {
- /* Restore Rd */
- tcpm_set_cc(port, TYPEC_CC_RD);
- timeout = 10*MSEC;
- set_state(port,
- PD_STATE_SNK_DISCONNECTED);
- break;
- }
- /* Wait for power supply to turn on */
- set_state_timeout(
- port,
- get_time().val +
- PD_POWER_SUPPLY_TURN_ON_DELAY,
- PD_STATE_SNK_SWAP_COMPLETE);
- }
- break;
- case PD_STATE_SNK_SWAP_COMPLETE:
- /* Send PS_RDY and change to source role */
- res = send_control(port, PD_CTRL_PS_RDY);
- if (res < 0) {
- /* Restore Rd */
- tcpm_set_cc(port, TYPEC_CC_RD);
- pd_power_supply_reset(port);
- timeout = 10 * MSEC;
- set_state(port, PD_STATE_SNK_DISCONNECTED);
- break;
- }
-
- /* Don't send GET_SINK_CAP on swap */
- snk_cap_count = PD_SNK_CAP_RETRIES+1;
- caps_count = 0;
- pd[port].msg_id = 0;
- pd_set_power_role(port, PD_ROLE_SOURCE);
- pd_update_roles(port);
- set_state(port, PD_STATE_SRC_DISCOVERY);
- timeout = 10*MSEC;
- break;
-#ifdef CONFIG_USBC_VCONN_SWAP
- case PD_STATE_VCONN_SWAP_SEND:
- if (pd[port].last_state != pd[port].task_state) {
- res = send_control(port, PD_CTRL_VCONN_SWAP);
- if (res < 0) {
- timeout = 10*MSEC;
- /*
- * If failed to get goodCRC, send
- * soft reset, otherwise ignore
- * failure.
- */
- set_state(port, res == -1 ?
- PD_STATE_SOFT_RESET :
- READY_RETURN_STATE(port));
- break;
- }
- /* Wait for accept or reject */
- set_state_timeout(port,
- get_time().val +
- PD_T_SENDER_RESPONSE,
- READY_RETURN_STATE(port));
- }
- break;
- case PD_STATE_VCONN_SWAP_INIT:
- if (pd[port].last_state != pd[port].task_state) {
- if (!(pd[port].flags & PD_FLAGS_VCONN_ON)) {
- /* Turn VCONN on and wait for it */
- set_vconn(port, 1);
- set_state_timeout(port,
- get_time().val +
- CONFIG_USBC_VCONN_SWAP_DELAY_US,
- PD_STATE_VCONN_SWAP_READY);
- } else {
- set_state_timeout(port,
- get_time().val +
- PD_T_VCONN_SOURCE_ON,
- READY_RETURN_STATE(port));
- }
- }
- break;
- case PD_STATE_VCONN_SWAP_READY:
- if (pd[port].last_state != pd[port].task_state) {
- if (!(pd[port].flags & PD_FLAGS_VCONN_ON)) {
- /* VCONN is now on, send PS_RDY */
- pd_set_vconn_role(port,
- PD_ROLE_VCONN_ON);
- res = send_control(port,
- PD_CTRL_PS_RDY);
- if (res == -1) {
- timeout = 10*MSEC;
- /*
- * If failed to get goodCRC,
- * send soft reset
- */
- set_state(port,
- PD_STATE_SOFT_RESET);
- break;
- }
- set_state(port,
- READY_RETURN_STATE(port));
- } else {
- /* Turn VCONN off and wait for it */
- set_vconn(port, 0);
- pd_set_vconn_role(port,
- PD_ROLE_VCONN_OFF);
- set_state_timeout(port,
- get_time().val +
- CONFIG_USBC_VCONN_SWAP_DELAY_US,
- READY_RETURN_STATE(port));
- }
- }
- break;
-#endif /* CONFIG_USBC_VCONN_SWAP */
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
- case PD_STATE_SOFT_RESET:
- if (pd[port].last_state != pd[port].task_state) {
- /* Message ID of soft reset is always 0 */
- invalidate_last_message_id(port);
- pd[port].msg_id = 0;
- res = send_control(port, PD_CTRL_SOFT_RESET);
-
- /* if soft reset failed, try hard reset. */
- if (res < 0) {
- set_state(port,
- PD_STATE_HARD_RESET_SEND);
- timeout = 5*MSEC;
- break;
- }
-
- set_state_timeout(
- port,
- get_time().val + PD_T_SENDER_RESPONSE,
- PD_STATE_HARD_RESET_SEND);
- }
- break;
- case PD_STATE_HARD_RESET_SEND:
- hard_reset_count++;
- if (pd[port].last_state != pd[port].task_state) {
- hard_reset_sent = 0;
- pd[port].hard_reset_complete_timer = 0;
- }
-#ifdef CONFIG_CHARGE_MANAGER
- if (pd[port].last_state == PD_STATE_SNK_DISCOVERY ||
- (pd[port].last_state == PD_STATE_SOFT_RESET &&
- (pd[port].flags & PD_FLAGS_VBUS_NEVER_LOW))) {
- pd[port].flags &= ~PD_FLAGS_VBUS_NEVER_LOW;
- /*
- * If discovery timed out, assume that we
- * have a dedicated charger attached. This
- * may not be a correct assumption according
- * to the specification, but it generally
- * works in practice and the harmful
- * effects of a wrong assumption here
- * are minimal.
- */
- charge_manager_update_dualrole(port,
- CAP_DEDICATED);
- }
-#endif
-
- if (hard_reset_sent)
- break;
-
- if (pd_transmit(port, TCPCI_MSG_TX_HARD_RESET, 0, NULL,
- AMS_START) < 0) {
- /*
- * likely a non-idle channel
- * TCPCI r2.0 v1.0 4.4.15:
- * the TCPC does not retry HARD_RESET
- * but we can try periodically until the timer
- * expires.
- */
- now = get_time();
- if (pd[port].hard_reset_complete_timer == 0) {
- pd[port].hard_reset_complete_timer =
- now.val +
- PD_T_HARD_RESET_COMPLETE;
- timeout = PD_T_HARD_RESET_RETRY;
- break;
- }
- if (now.val <
- pd[port].hard_reset_complete_timer) {
- CPRINTS("C%d: Retrying hard reset",
- port);
- timeout = PD_T_HARD_RESET_RETRY;
- break;
- }
- /*
- * PD 2.0 spec, section 6.5.11.1
- * Pretend TX_HARD_RESET succeeded after
- * timeout.
- */
- }
-
- hard_reset_sent = 1;
- /*
- * If we are source, delay before cutting power
- * to allow sink time to get hard reset.
- */
- if (pd[port].power_role == PD_ROLE_SOURCE) {
- set_state_timeout(port,
- get_time().val + PD_T_PS_HARD_RESET,
- PD_STATE_HARD_RESET_EXECUTE);
- } else {
- set_state(port, PD_STATE_HARD_RESET_EXECUTE);
- timeout = 10 * MSEC;
- }
- break;
- case PD_STATE_HARD_RESET_EXECUTE:
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /*
- * If hard reset while in the last stages of power
- * swap, then we need to restore our CC resistor.
- */
- if (pd[port].last_state == PD_STATE_SNK_SWAP_STANDBY)
- tcpm_set_cc(port, TYPEC_CC_RD);
-#endif
-
- /* reset our own state machine */
- pd_execute_hard_reset(port);
- timeout = 10*MSEC;
- break;
-#ifdef CONFIG_COMMON_RUNTIME
- case PD_STATE_BIST_RX:
- send_bist_cmd(port);
- /* Delay at least enough for partner to finish BIST */
- timeout = PD_T_BIST_RECEIVE + 20*MSEC;
- /* Set to appropriate port disconnected state */
- set_state(port, DUAL_ROLE_IF_ELSE(port,
- PD_STATE_SNK_DISCONNECTED,
- PD_STATE_SRC_DISCONNECTED));
- break;
- case PD_STATE_BIST_TX:
- pd_transmit(port, TCPCI_MSG_TX_BIST_MODE_2, 0, NULL,
- AMS_START);
- /* Delay at least enough to finish sending BIST */
- timeout = PD_T_BIST_TRANSMIT + 20*MSEC;
- /* Set to appropriate port disconnected state */
- set_state(port, DUAL_ROLE_IF_ELSE(port,
- PD_STATE_SNK_DISCONNECTED,
- PD_STATE_SRC_DISCONNECTED));
- break;
-#endif
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- case PD_STATE_DRP_AUTO_TOGGLE:
- {
- enum pd_drp_next_states next_state;
-
- assert(auto_toggle_supported);
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /*
- * If SW decided we should be in a low power state and
- * the CC lines did not change, then don't talk with the
- * TCPC otherwise we might wake it up.
- */
- if (pd[port].flags & PD_FLAGS_LPM_REQUESTED &&
- !(evt & PD_EVENT_CC))
- break;
-
- /*
- * Debounce low power mode exit. Some TCPCs need time
- * for the CC_STATUS register to be stable after exiting
- * low power mode.
- */
- if (pd[port].flags & PD_FLAGS_LPM_EXIT) {
- uint64_t now;
-
- now = get_time().val;
- if (now < pd[port].low_power_exit_time)
- break;
-
- CPRINTS("TCPC p%d Exit Low Power Mode done",
- port);
- pd[port].flags &= ~PD_FLAGS_LPM_EXIT;
- }
-#endif
-
- /*
- * Check for connection
- *
- * Send FALSE for supports_auto_toggle to not change
- * the current return value of UNATTACHED instead of
- * the auto-toggle ATTACHED_WAIT response for TCPMv1.
- */
- tcpm_get_cc(port, &cc1, &cc2);
-
- next_state = drp_auto_toggle_next_state(
- &pd[port].drp_sink_time,
- pd[port].power_role,
- drp_state[port],
- cc1, cc2, false);
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /*
- * The next state is not determined just by what is
- * attached, but also depends on DRP_STATE. Regardless
- * of next state, if nothing is attached, then always
- * request low power mode.
- */
- if (cc_is_open(cc1, cc2))
- pd[port].flags |= PD_FLAGS_LPM_REQUESTED;
-#endif
- if (next_state == DRP_TC_DEFAULT) {
- if (PD_DEFAULT_STATE(port) ==
- PD_STATE_SNK_DISCONNECTED)
- next_state = DRP_TC_UNATTACHED_SNK;
- else
- next_state = DRP_TC_UNATTACHED_SRC;
- }
-
- if (next_state == DRP_TC_UNATTACHED_SNK) {
- /*
- * The TCPCI comes out of auto toggle with
- * a prospective connection. It is expecting
- * us to set the CC lines to what it is
- * thinking is best or it goes direct back to
- * unattached. So get the SNK polarity to
- * be able to setup the CC lines to avoid this.
- */
- pd[port].polarity = get_snk_polarity(cc1, cc2);
-
- tcpm_set_cc(port, TYPEC_CC_RD);
- pd_set_power_role(port, PD_ROLE_SINK);
- timeout = 2*MSEC;
- set_state(port, PD_STATE_SNK_DISCONNECTED);
- } else if (next_state == DRP_TC_UNATTACHED_SRC) {
- /*
- * The TCPCI comes out of auto toggle with
- * a prospective connection. It is expecting
- * us to set the CC lines to what it is
- * thinking is best or it goes direct back to
- * unattached. So get the SNK polarity to
- * be able to setup the CC lines to avoid this.
- */
- pd[port].polarity = get_src_polarity(cc1, cc2);
-
- tcpm_set_cc(port, TYPEC_CC_RP);
- pd_set_power_role(port, PD_ROLE_SOURCE);
- timeout = 2*MSEC;
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- } else {
- /*
- * We are staying in PD_STATE_DRP_AUTO_TOGGLE,
- * therefore enable auto-toggle.
- */
- tcpm_enable_drp_toggle(port);
- pd[port].flags |= PD_FLAGS_TCPC_DRP_TOGGLE;
- set_state(port, PD_STATE_DRP_AUTO_TOGGLE);
- }
-
- break;
- }
-#endif
- case PD_STATE_ENTER_USB:
- if (pd[port].last_state != pd[port].task_state) {
- set_state_timeout(port,
- get_time().val + PD_T_SENDER_RESPONSE,
- READY_RETURN_STATE(port));
- }
- break;
- default:
- break;
- }
-
- pd[port].last_state = this_state;
-
- /*
- * Check for state timeout, and if not check if need to adjust
- * timeout value to wake up on the next state timeout.
- */
- now = get_time();
- if (pd[port].timeout) {
- if (now.val >= pd[port].timeout) {
- set_state(port, pd[port].timeout_state);
- /* On a state timeout, run next state soon */
- timeout = timeout < 10*MSEC ? timeout : 10*MSEC;
- } else if (pd[port].timeout - now.val < timeout) {
- timeout = pd[port].timeout - now.val;
- }
- }
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- /* Determine if we need to put the TCPC in low power mode */
- if (pd[port].flags & PD_FLAGS_LPM_REQUESTED &&
- !(pd[port].flags & PD_FLAGS_LPM_ENGAGED)) {
- int64_t time_left;
-
- /* If any task prevents LPM, wait another debounce */
- if (pd[port].tasks_preventing_lpm) {
- pd[port].low_power_time =
- PD_LPM_DEBOUNCE_US + now.val;
- }
-
- time_left = pd[port].low_power_time - now.val;
- if (time_left <= 0) {
- pd[port].flags |= PD_FLAGS_LPM_ENGAGED;
- pd[port].flags |= PD_FLAGS_LPM_TRANSITION;
- tcpm_enter_low_power_mode(port);
- pd[port].flags &= ~PD_FLAGS_LPM_TRANSITION;
- tcpc_prints("Enter Low Power Mode", port);
- timeout = -1;
- } else if (timeout < 0 || timeout > time_left) {
- timeout = time_left;
- }
- }
-#endif
-
- /* Check for disconnection if we're connected */
- if (!pd_is_connected(port))
- continue;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- if (pd_is_power_swapping(port))
- continue;
-#endif
- if (pd[port].power_role == PD_ROLE_SOURCE) {
- /* Source: detect disconnect by monitoring CC */
- tcpm_get_cc(port, &cc1, &cc2);
- if (polarity_rm_dts(pd[port].polarity))
- cc1 = cc2;
- if (cc1 == TYPEC_CC_VOLT_OPEN) {
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- /* Debouncing */
- timeout = 10*MSEC;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /*
- * If Try.SRC is configured, then ATTACHED_SRC
- * needs to transition to TryWait.SNK. Change
- * power role to SNK and start state timer.
- */
- if (pd_try_src_enable) {
- /* Swap roles to sink */
- pd_set_power_role(port, PD_ROLE_SINK);
- tcpm_set_cc(port, TYPEC_CC_RD);
- /* Set timer for TryWait.SNK state */
- pd[port].try_src_marker = get_time().val
- + PD_T_DEBOUNCE;
- /* Advance to TryWait.SNK state */
- set_state(port,
- PD_STATE_SNK_DISCONNECTED);
- /* Mark state as TryWait.SNK */
- pd[port].flags |= PD_FLAGS_TRY_SRC;
- }
-#endif
- }
- }
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /*
- * Sink disconnect if VBUS is low and
- * 1) we are not waiting for VBUS to debounce after a power
- * role swap.
- * 2) we are not recovering from a hard reset.
- */
- if (pd[port].power_role == PD_ROLE_SINK &&
- pd[port].vbus_debounce_time < get_time().val &&
- !pd_is_vbus_present(port) &&
- pd[port].task_state != PD_STATE_SNK_HARD_RESET_RECOVER &&
- pd[port].task_state != PD_STATE_HARD_RESET_EXECUTE) {
- /* Sink: detect disconnect by monitoring VBUS */
- set_state(port, PD_STATE_SNK_DISCONNECTED);
- /* set timeout small to reconnect fast */
- timeout = 5*MSEC;
- }
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
- }
-}
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-static void pd_chipset_resume(void)
-{
- int i;
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
-#ifdef CONFIG_CHARGE_MANAGER
- if (charge_manager_get_active_charge_port() != i)
-#endif
- pd[i].flags |= PD_FLAGS_CHECK_PR_ROLE |
- PD_FLAGS_CHECK_DR_ROLE;
- pd_set_dual_role(i, PD_DRP_TOGGLE_ON);
- }
-
- CPRINTS("PD:S3->S0");
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, pd_chipset_resume, HOOK_PRIO_DEFAULT);
-
-static void pd_chipset_suspend(void)
-{
- int i;
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- pd_set_dual_role(i, PD_DRP_TOGGLE_OFF);
- CPRINTS("PD:S0->S3");
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, pd_chipset_suspend, HOOK_PRIO_DEFAULT);
-
-static void pd_chipset_startup(void)
-{
- int i;
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- pd_set_dual_role_no_wakeup(i, PD_DRP_TOGGLE_OFF);
- pd[i].flags |= PD_FLAGS_CHECK_IDENTITY;
- /* Reset cable attributes and flags */
- reset_pd_cable(i);
- task_set_event(PD_PORT_TO_TASK_ID(i),
- PD_EVENT_POWER_STATE_CHANGE |
- PD_EVENT_UPDATE_DUAL_ROLE);
- }
- CPRINTS("PD:S5->S3");
-}
-DECLARE_HOOK(HOOK_CHIPSET_STARTUP, pd_chipset_startup, HOOK_PRIO_DEFAULT);
-
-static void pd_chipset_shutdown(void)
-{
- int i;
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- pd_set_dual_role_no_wakeup(i, PD_DRP_FORCE_SINK);
- task_set_event(PD_PORT_TO_TASK_ID(i),
- PD_EVENT_POWER_STATE_CHANGE |
- PD_EVENT_UPDATE_DUAL_ROLE);
- }
- CPRINTS("PD:S3->S5");
-}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pd_chipset_shutdown, HOOK_PRIO_DEFAULT);
-
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
-
-#ifdef CONFIG_COMMON_RUNTIME
-
-static void pd_control_resume(int port)
-{
- if (pd[port].task_state != PD_STATE_SUSPENDED)
- return;
-
- set_state(port, PD_DEFAULT_STATE(port));
- /*
- * Since we did not service interrupts while we were suspended,
- * see if there is a waiting interrupt to be serviced. If the
- * interrupt line isn't asserted, we won't communicate with the
- * TCPC.
- */
- if (IS_ENABLED(HAS_TASK_PD_INT_C0))
- schedule_deferred_pd_interrupt(port);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-/*
- * (suspend=1) request pd_task transition to the suspended state. hang
- * around for a while until we observe the state change. this can
- * take a while (like 300ms) on startup when pd_task is sleeping in
- * tcpci_tcpm_init.
- *
- * (suspend=0) force pd_task out of the suspended state and into the
- * port's default state.
- */
-
-void pd_set_suspend(int port, int suspend)
-{
- int tries = 300;
-
- if (suspend) {
- pd[port].req_suspend_state = 1;
- do {
- task_wake(PD_PORT_TO_TASK_ID(port));
- if (pd[port].task_state == PD_STATE_SUSPENDED)
- break;
- msleep(1);
- } while (--tries != 0);
- if (!tries)
- tcpc_prints("set_suspend failed!", port);
- } else {
- pd_control_resume(port);
- }
-}
-
-int pd_is_port_enabled(int port)
-{
- switch (pd[port].task_state) {
- case PD_STATE_DISABLED:
- case PD_STATE_SUSPENDED:
- return 0;
- default:
- return 1;
- }
-}
-
-#if defined(CONFIG_USB_PD_ALT_MODE) && !defined(CONFIG_USB_PD_ALT_MODE_DFP)
-void pd_send_hpd(int port, enum hpd_event hpd)
-{
- uint32_t data[1];
- int opos = pd_alt_mode(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT);
- if (!opos)
- return;
-
- data[0] = VDO_DP_STATUS((hpd == hpd_irq), /* IRQ_HPD */
- (hpd != hpd_low), /* HPD_HI|LOW */
- 0, /* request exit DP */
- 0, /* request exit USB */
- 0, /* MF pref */
- 1, /* enabled */
- 0, /* power low */
- 0x2);
- pd_send_vdm(port, USB_SID_DISPLAYPORT,
- VDO_OPOS(opos) | CMD_ATTENTION, data, 1);
- /* Wait until VDM is done. */
- while (pd[0].vdm_state > 0)
- task_wait_event(USB_PD_RX_TMOUT_US *
- (CONFIG_PD_RETRY_COUNT + 1));
-}
-#endif
-
-int pd_fetch_acc_log_entry(int port)
-{
- timestamp_t timeout;
-
- /* Cannot send a VDM now, the host should retry */
- if (pd[port].vdm_state > 0)
- return pd[port].vdm_state == VDM_STATE_BUSY ?
- EC_RES_BUSY : EC_RES_UNAVAILABLE;
-
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_GET_LOG, NULL, 0);
- timeout.val = get_time().val + 75*MSEC;
-
- /* Wait until VDM is done */
- while ((pd[port].vdm_state > 0) &&
- (get_time().val < timeout.val))
- task_wait_event(10*MSEC);
-
- if (pd[port].vdm_state > 0)
- return EC_RES_TIMEOUT;
- else if (pd[port].vdm_state < 0)
- return EC_RES_ERROR;
-
- return EC_RES_SUCCESS;
-}
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
-void pd_request_source_voltage(int port, int mv)
-{
- pd_set_max_voltage(mv);
-
- if (pd[port].task_state == PD_STATE_SNK_READY ||
- pd[port].task_state == PD_STATE_SNK_TRANSITION) {
- /* Set flag to send new power request in pd_task */
- pd[port].new_power_request = 1;
- } else {
- pd_set_power_role(port, PD_ROLE_SINK);
- tcpm_set_cc(port, TYPEC_CC_RD);
- set_state(port, PD_STATE_SNK_DISCONNECTED);
- }
-
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void pd_set_external_voltage_limit(int port, int mv)
-{
- pd_set_max_voltage(mv);
-
- if (pd[port].task_state == PD_STATE_SNK_READY ||
- pd[port].task_state == PD_STATE_SNK_TRANSITION) {
- /* Set flag to send new power request in pd_task */
- pd[port].new_power_request = 1;
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-void pd_update_contract(int port)
-{
- if ((pd[port].task_state >= PD_STATE_SRC_NEGOCIATE) &&
- (pd[port].task_state <= PD_STATE_SRC_GET_SINK_CAP)) {
- pd[port].flags |= PD_FLAGS_UPDATE_SRC_CAPS;
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
-
-static int command_pd(int argc, char **argv)
-{
- int port;
- char *e;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- if (!strcasecmp(argv[1], "dump")) {
- if (argc >= 3) {
-#ifdef CONFIG_USB_PD_DEBUG_LEVEL
- return EC_ERROR_PARAM2;
-#else
- int level = strtoi(argv[2], &e, 10);
- if (*e)
- return EC_ERROR_PARAM2;
- debug_level = level;
-#endif
- }
- ccprintf("debug=%d\n", debug_level);
-
- return EC_SUCCESS;
- }
-
-#ifdef CONFIG_CMD_PD
-#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO
- else if (!strncasecmp(argv[1], "rwhashtable", 3)) {
- int i;
- struct ec_params_usb_pd_rw_hash_entry *p;
- for (i = 0; i < RW_HASH_ENTRIES; i++) {
- p = &rw_hash_table[i];
- pd_dev_dump_info(p->dev_id, p->dev_rw_hash);
- }
- return EC_SUCCESS;
- }
-#endif /* CONFIG_CMD_PD_DEV_DUMP_INFO */
-#ifdef CONFIG_USB_PD_TRY_SRC
- else if (!strncasecmp(argv[1], "trysrc", 6)) {
- int enable;
-
- if (argc >= 3) {
- enable = strtoi(argv[2], &e, 10);
- if (*e)
- return EC_ERROR_PARAM3;
- pd_try_src_enable = enable ? 1 : 0;
- }
-
- ccprintf("Try.SRC %s\n", pd_try_src_enable ? "on" : "off");
- return EC_SUCCESS;
- }
-#endif
-#endif
- else if (!strcasecmp(argv[1], "version")) {
- ccprintf("%d\n", PD_STACK_VERSION);
- return EC_SUCCESS;
- }
-
- /* command: pd <port> <subcmd> [args] */
- port = strtoi(argv[1], &e, 10);
- if (argc < 3)
- return EC_ERROR_PARAM_COUNT;
- if (*e || port >= board_get_usb_pd_port_count())
- return EC_ERROR_PARAM2;
-#if defined(CONFIG_CMD_PD) && defined(CONFIG_USB_PD_DUAL_ROLE)
-
- if (!strcasecmp(argv[2], "tx")) {
- set_state(port, PD_STATE_SNK_DISCOVERY);
- task_wake(PD_PORT_TO_TASK_ID(port));
- } else if (!strcasecmp(argv[2], "bist_rx")) {
- set_state(port, PD_STATE_BIST_RX);
- task_wake(PD_PORT_TO_TASK_ID(port));
- } else if (!strcasecmp(argv[2], "bist_tx")) {
- if (*e)
- return EC_ERROR_PARAM3;
- set_state(port, PD_STATE_BIST_TX);
- task_wake(PD_PORT_TO_TASK_ID(port));
- } else if (!strcasecmp(argv[2], "charger")) {
- pd_set_power_role(port, PD_ROLE_SOURCE);
- tcpm_set_cc(port, TYPEC_CC_RP);
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- task_wake(PD_PORT_TO_TASK_ID(port));
- } else if (!strncasecmp(argv[2], "dev", 3)) {
- int max_volt;
- if (argc >= 4)
- max_volt = strtoi(argv[3], &e, 10) * 1000;
- else
- max_volt = pd_get_max_voltage();
-
- pd_request_source_voltage(port, max_volt);
- ccprintf("max req: %dmV\n", max_volt);
- } else if (!strcasecmp(argv[2], "disable")) {
- pd_comm_enable(port, 0);
- ccprintf("Port C%d disable\n", port);
- return EC_SUCCESS;
- } else if (!strcasecmp(argv[2], "enable")) {
- pd_comm_enable(port, 1);
- ccprintf("Port C%d enabled\n", port);
- return EC_SUCCESS;
- } else if (!strncasecmp(argv[2], "hard", 4)) {
- set_state(port, PD_STATE_HARD_RESET_SEND);
- task_wake(PD_PORT_TO_TASK_ID(port));
- } else if (!strncasecmp(argv[2], "info", 4)) {
- int i;
- ccprintf("Hash ");
- for (i = 0; i < PD_RW_HASH_SIZE / 4; i++)
- ccprintf("%08x ", pd[port].dev_rw_hash[i]);
- ccprintf("\nImage %s\n",
- ec_image_to_string(pd[port].current_image));
- } else if (!strncasecmp(argv[2], "soft", 4)) {
- set_state(port, PD_STATE_SOFT_RESET);
- task_wake(PD_PORT_TO_TASK_ID(port));
- } else if (!strncasecmp(argv[2], "swap", 4)) {
- if (argc < 4)
- return EC_ERROR_PARAM_COUNT;
-
- if (!strncasecmp(argv[3], "power", 5))
- pd_request_power_swap(port);
- else if (!strncasecmp(argv[3], "data", 4))
- pd_request_data_swap(port);
-#ifdef CONFIG_USBC_VCONN_SWAP
- else if (!strncasecmp(argv[3], "vconn", 5))
- pd_request_vconn_swap(port);
-#endif
- else
- return EC_ERROR_PARAM3;
- } else if (!strncasecmp(argv[2], "srccaps", 7)) {
- pd_srccaps_dump(port);
- } else if (!strncasecmp(argv[2], "ping", 4)) {
- int enable;
-
- if (argc > 3) {
- enable = strtoi(argv[3], &e, 10);
- if (*e)
- return EC_ERROR_PARAM3;
- pd_ping_enable(port, enable);
- }
-
- ccprintf("Pings %s\n",
- (pd[port].flags & PD_FLAGS_PING_ENABLED) ?
- "on" : "off");
- } else if (!strncasecmp(argv[2], "vdm", 3)) {
- if (argc < 4)
- return EC_ERROR_PARAM_COUNT;
-
- if (!strncasecmp(argv[3], "ping", 4)) {
- uint32_t enable;
- if (argc < 5)
- return EC_ERROR_PARAM_COUNT;
- enable = strtoi(argv[4], &e, 10);
- if (*e)
- return EC_ERROR_PARAM4;
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_PING_ENABLE,
- &enable, 1);
- } else if (!strncasecmp(argv[3], "curr", 4)) {
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_CURRENT,
- NULL, 0);
- } else if (!strncasecmp(argv[3], "vers", 4)) {
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_VERSION,
- NULL, 0);
- } else {
- return EC_ERROR_PARAM_COUNT;
- }
-#if defined(CONFIG_CMD_PD) && defined(CONFIG_CMD_PD_FLASH)
- } else if (!strncasecmp(argv[2], "flash", 4)) {
- return remote_flashing(argc, argv);
-#endif
-#if defined(CONFIG_CMD_PD) && defined(CONFIG_USB_PD_DUAL_ROLE)
- } else if (!strcasecmp(argv[2], "dualrole")) {
- if (argc < 4) {
- ccprintf("dual-role toggling: ");
- switch (drp_state[port]) {
- case PD_DRP_TOGGLE_ON:
- ccprintf("on\n");
- break;
- case PD_DRP_TOGGLE_OFF:
- ccprintf("off\n");
- break;
- case PD_DRP_FREEZE:
- ccprintf("freeze\n");
- break;
- case PD_DRP_FORCE_SINK:
- ccprintf("force sink\n");
- break;
- case PD_DRP_FORCE_SOURCE:
- ccprintf("force source\n");
- break;
- }
- } else {
- if (!strcasecmp(argv[3], "on"))
- pd_set_dual_role(port, PD_DRP_TOGGLE_ON);
- else if (!strcasecmp(argv[3], "off"))
- pd_set_dual_role(port, PD_DRP_TOGGLE_OFF);
- else if (!strcasecmp(argv[3], "freeze"))
- pd_set_dual_role(port, PD_DRP_FREEZE);
- else if (!strcasecmp(argv[3], "sink"))
- pd_set_dual_role(port, PD_DRP_FORCE_SINK);
- else if (!strcasecmp(argv[3], "source"))
- pd_set_dual_role(port,
- PD_DRP_FORCE_SOURCE);
- else
- return EC_ERROR_PARAM4;
- }
- return EC_SUCCESS;
-#endif
- } else
-#endif
- if (!strncasecmp(argv[2], "state", 5)) {
- ccprintf("Port C%d CC%d, %s - Role: %s-%s%s "
- "State: %d(%s), Flags: 0x%04x\n",
- port, pd[port].polarity + 1,
- pd_comm_is_enabled(port) ? "Ena" : "Dis",
- pd[port].power_role == PD_ROLE_SOURCE ? "SRC" : "SNK",
- pd[port].data_role == PD_ROLE_DFP ? "DFP" : "UFP",
- (pd[port].flags & PD_FLAGS_VCONN_ON) ? "-VC" : "",
- pd[port].task_state,
- debug_level > 0 ? pd_get_task_state_name(port) : "",
- pd[port].flags);
- } else {
- return EC_ERROR_PARAM1;
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(pd, command_pd,
- "version"
- "|dump"
-#ifdef CONFIG_USB_PD_TRY_SRC
- "|trysrc"
-#endif
- " [0|1|2]"
-#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO
- "|rwhashtable"
-#endif
- "\n\t<port> state"
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- "|tx|bist_rx|bist_tx|charger|dev"
- "\n\t<port> disable|enable|soft|info|hard|ping"
- "\n\t<port> dualrole [on|off|freeze|sink|source]"
- "\n\t<port> swap [power|data|vconn]"
- "\n\t<port> vdm [ping|curr|vers]"
-#ifdef CONFIG_CMD_PD_FLASH
- "\n\t<port> flash [erase|reboot|signature|info|version]"
-#endif /* CONFIG_CMD_PD_FLASH */
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
- "\n\t<port> srccaps",
- "USB PD");
-
-#ifdef HAS_TASK_HOSTCMD
-
-#ifdef CONFIG_HOSTCMD_FLASHPD
-static enum ec_status hc_remote_flash(struct host_cmd_handler_args *args)
-{
- const struct ec_params_usb_pd_fw_update *p = args->params;
- int port = p->port;
- const uint32_t *data = &(p->size) + 1;
- int i, size, rv = EC_RES_SUCCESS;
- timestamp_t timeout;
-
- if (port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- if (p->size + sizeof(*p) > args->params_size)
- return EC_RES_INVALID_PARAM;
-
-#if defined(CONFIG_BATTERY) && \
- (defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \
- defined(CONFIG_BATTERY_PRESENT_GPIO))
- /*
- * Do not allow PD firmware update if no battery and this port
- * is sinking power, because we will lose power.
- */
- if (battery_is_present() != BP_YES &&
- charge_manager_get_active_charge_port() == port)
- return EC_RES_UNAVAILABLE;
-#endif
-
- /*
- * Busy still with a VDM that host likely generated. 1 deep VDM queue
- * so just return for retry logic on host side to deal with.
- */
- if (pd[port].vdm_state > 0)
- return EC_RES_BUSY;
-
- switch (p->cmd) {
- case USB_PD_FW_REBOOT:
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_REBOOT, NULL, 0);
-
- /*
- * Return immediately to free pending i2c bus. Host needs to
- * manage this delay.
- */
- return EC_RES_SUCCESS;
-
- case USB_PD_FW_FLASH_ERASE:
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_ERASE, NULL, 0);
-
- /*
- * Return immediately. Host needs to manage delays here which
- * can be as long as 1.2 seconds on 64KB RW flash.
- */
- return EC_RES_SUCCESS;
-
- case USB_PD_FW_ERASE_SIG:
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_ERASE_SIG, NULL, 0);
- timeout.val = get_time().val + 500*MSEC;
- break;
-
- case USB_PD_FW_FLASH_WRITE:
- /* Data size must be a multiple of 4 */
- if (!p->size || p->size % 4)
- return EC_RES_INVALID_PARAM;
-
- size = p->size / 4;
- for (i = 0; i < size; i += VDO_MAX_SIZE - 1) {
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_FLASH_WRITE,
- data + i, MIN(size - i, VDO_MAX_SIZE - 1));
- timeout.val = get_time().val + 500*MSEC;
-
- /* Wait until VDM is done */
- while ((pd[port].vdm_state > 0) &&
- (get_time().val < timeout.val))
- task_wait_event(10*MSEC);
-
- if (pd[port].vdm_state > 0)
- return EC_RES_TIMEOUT;
- }
- return EC_RES_SUCCESS;
-
- default:
- return EC_RES_INVALID_PARAM;
- break;
- }
-
- /* Wait until VDM is done or timeout */
- while ((pd[port].vdm_state > 0) && (get_time().val < timeout.val))
- task_wait_event(50*MSEC);
-
- if ((pd[port].vdm_state > 0) ||
- (pd[port].vdm_state == VDM_STATE_ERR_TMOUT))
- rv = EC_RES_TIMEOUT;
- else if (pd[port].vdm_state < 0)
- rv = EC_RES_ERROR;
-
- return rv;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_PD_FW_UPDATE,
- hc_remote_flash,
- EC_VER_MASK(0));
-#endif /* CONFIG_HOSTCMD_FLASHPD */
-
-#endif /* HAS_TASK_HOSTCMD */
-
-
-#endif /* CONFIG_COMMON_RUNTIME */
diff --git a/common/usb_pd_tcpc.c b/common/usb_pd_tcpc.c
deleted file mode 100644
index 1aaee29abc..0000000000
--- a/common/usb_pd_tcpc.c
+++ /dev/null
@@ -1,1468 +0,0 @@
-/* Copyright 2015 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.
- */
-
-#include "adc.h"
-#include "common.h"
-#include "config.h"
-#include "console.h"
-#include "crc.h"
-#include "ec_commands.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "registers.h"
-#include "system.h"
-#include "task.h"
-#include "tcpm/tcpci.h"
-#include "tcpm/tcpm.h"
-#include "timer.h"
-#include "util.h"
-#include "usb_pd.h"
-#include "usb_pd_config.h"
-#include "usb_pd_tcpm.h"
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-
-/*
- * Debug log level - higher number == more log
- * Level 0: Log state transitions
- * Level 1: Level 0, plus packet info
- * Level 2: Level 1, plus ping packet and packet dump on error
- *
- * Note that higher log level causes timing changes and thus may affect
- * performance.
- */
-static int debug_level;
-
-static struct mutex pd_crc_lock;
-#else
-#define CPRINTF(format, args...)
-static const int debug_level;
-#endif
-
-/* Encode 5 bits using Biphase Mark Coding */
-#define BMC(x) ((x & 1 ? 0x001 : 0x3FF) \
- ^ (x & 2 ? 0x004 : 0x3FC) \
- ^ (x & 4 ? 0x010 : 0x3F0) \
- ^ (x & 8 ? 0x040 : 0x3C0) \
- ^ (x & 16 ? 0x100 : 0x300))
-
-/* 4b/5b + Bimark Phase encoding */
-static const uint16_t bmc4b5b[] = {
-/* 0 = 0000 */ BMC(0x1E) /* 11110 */,
-/* 1 = 0001 */ BMC(0x09) /* 01001 */,
-/* 2 = 0010 */ BMC(0x14) /* 10100 */,
-/* 3 = 0011 */ BMC(0x15) /* 10101 */,
-/* 4 = 0100 */ BMC(0x0A) /* 01010 */,
-/* 5 = 0101 */ BMC(0x0B) /* 01011 */,
-/* 6 = 0110 */ BMC(0x0E) /* 01110 */,
-/* 7 = 0111 */ BMC(0x0F) /* 01111 */,
-/* 8 = 1000 */ BMC(0x12) /* 10010 */,
-/* 9 = 1001 */ BMC(0x13) /* 10011 */,
-/* A = 1010 */ BMC(0x16) /* 10110 */,
-/* B = 1011 */ BMC(0x17) /* 10111 */,
-/* C = 1100 */ BMC(0x1A) /* 11010 */,
-/* D = 1101 */ BMC(0x1B) /* 11011 */,
-/* E = 1110 */ BMC(0x1C) /* 11100 */,
-/* F = 1111 */ BMC(0x1D) /* 11101 */,
-/* Sync-1 K-code 11000 Startsynch #1 */
-/* Sync-2 K-code 10001 Startsynch #2 */
-/* RST-1 K-code 00111 Hard Reset #1 */
-/* RST-2 K-code 11001 Hard Reset #2 */
-/* EOP K-code 01101 EOP End Of Packet */
-/* Reserved Error 00000 */
-/* Reserved Error 00001 */
-/* Reserved Error 00010 */
-/* Reserved Error 00011 */
-/* Reserved Error 00100 */
-/* Reserved Error 00101 */
-/* Reserved Error 00110 */
-/* Reserved Error 01000 */
-/* Reserved Error 01100 */
-/* Reserved Error 10000 */
-/* Reserved Error 11111 */
-};
-
-static const uint8_t dec4b5b[] = {
-/* Error */ 0x10 /* 00000 */,
-/* Error */ 0x10 /* 00001 */,
-/* Error */ 0x10 /* 00010 */,
-/* Error */ 0x10 /* 00011 */,
-/* Error */ 0x10 /* 00100 */,
-/* Error */ 0x10 /* 00101 */,
-/* Error */ 0x10 /* 00110 */,
-/* RST-1 */ 0x13 /* 00111 K-code: Hard Reset #1 */,
-/* Error */ 0x10 /* 01000 */,
-/* 1 = 0001 */ 0x01 /* 01001 */,
-/* 4 = 0100 */ 0x04 /* 01010 */,
-/* 5 = 0101 */ 0x05 /* 01011 */,
-/* Error */ 0x10 /* 01100 */,
-/* EOP */ 0x15 /* 01101 K-code: EOP End Of Packet */,
-/* 6 = 0110 */ 0x06 /* 01110 */,
-/* 7 = 0111 */ 0x07 /* 01111 */,
-/* Error */ 0x10 /* 10000 */,
-/* Sync-2 */ 0x12 /* 10001 K-code: Startsynch #2 */,
-/* 8 = 1000 */ 0x08 /* 10010 */,
-/* 9 = 1001 */ 0x09 /* 10011 */,
-/* 2 = 0010 */ 0x02 /* 10100 */,
-/* 3 = 0011 */ 0x03 /* 10101 */,
-/* A = 1010 */ 0x0A /* 10110 */,
-/* B = 1011 */ 0x0B /* 10111 */,
-/* Sync-1 */ 0x11 /* 11000 K-code: Startsynch #1 */,
-/* RST-2 */ 0x14 /* 11001 K-code: Hard Reset #2 */,
-/* C = 1100 */ 0x0C /* 11010 */,
-/* D = 1101 */ 0x0D /* 11011 */,
-/* E = 1110 */ 0x0E /* 11100 */,
-/* F = 1111 */ 0x0F /* 11101 */,
-/* 0 = 0000 */ 0x00 /* 11110 */,
-/* Error */ 0x10 /* 11111 */,
-};
-
-/* Start of Packet sequence : three Sync-1 K-codes, then one Sync-2 K-code */
-#define PD_SOP (PD_SYNC1 | (PD_SYNC1<<5) | (PD_SYNC1<<10) | (PD_SYNC2<<15))
-#define PD_SOP_PRIME (PD_SYNC1 | (PD_SYNC1<<5) | \
- (PD_SYNC3<<10) | (PD_SYNC3<<15))
-#define PD_SOP_PRIME_PRIME (PD_SYNC1 | (PD_SYNC3<<5) | \
- (PD_SYNC1<<10) | (PD_SYNC3<<15))
-
-/* Hard Reset sequence : three RST-1 K-codes, then one RST-2 K-code */
-#define PD_HARD_RESET (PD_RST1 | (PD_RST1 << 5) |\
- (PD_RST1 << 10) | (PD_RST2 << 15))
-
-/*
- * Polarity based on 'DFP Perspective' (see table USB Type-C Cable and Connector
- * Specification)
- *
- * CC1 CC2 STATE POSITION
- * ----------------------------------------
- * open open NC N/A
- * Rd open UFP attached 1
- * open Rd UFP attached 2
- * open Ra pwr cable no UFP N/A
- * Ra open pwr cable no UFP N/A
- * Rd Ra pwr cable & UFP 1
- * Ra Rd pwr cable & UFP 2
- * Rd Rd dbg accessory N/A
- * Ra Ra audio accessory N/A
- *
- * Note, V(Rd) > V(Ra)
- */
-#ifndef PD_SRC_RD_THRESHOLD
-#define PD_SRC_RD_THRESHOLD PD_SRC_DEF_RD_THRESH_MV
-#endif
-#ifndef PD_SRC_VNC
-#define PD_SRC_VNC PD_SRC_DEF_VNC_MV
-#endif
-
-#ifndef CC_RA
-#define CC_RA(port, cc, sel) (cc < PD_SRC_RD_THRESHOLD)
-#endif
-#define CC_RD(cc) ((cc >= PD_SRC_RD_THRESHOLD) && (cc < PD_SRC_VNC))
-#ifndef CC_NC
-#define CC_NC(port, cc, sel) (cc >= PD_SRC_VNC)
-#endif
-
-/*
- * Polarity based on 'UFP Perspective'.
- *
- * CC1 CC2 STATE POSITION
- * ----------------------------------------
- * open open NC N/A
- * Rp open DFP attached 1
- * open Rp DFP attached 2
- * Rp Rp Accessory attached N/A
- */
-#ifndef PD_SNK_VA
-#define PD_SNK_VA PD_SNK_VA_MV
-#endif
-
-#define CC_RP(cc) (cc >= PD_SNK_VA)
-
-/*
- * Type C power source charge current limits are identified by their cc
- * voltage (set by selecting the proper Rd resistor). Any voltage below
- * TYPE_C_SRC_500_THRESHOLD will not be identified as a type C charger.
- */
-#define TYPE_C_SRC_500_THRESHOLD PD_SRC_RD_THRESHOLD
-#define TYPE_C_SRC_1500_THRESHOLD 660 /* mV */
-#define TYPE_C_SRC_3000_THRESHOLD 1230 /* mV */
-
-/* Convert TCPC Alert register to index into pd.alert[] */
-#define ALERT_REG_TO_INDEX(reg) (reg - TCPC_REG_ALERT)
-
-/* PD transmit errors */
-enum pd_tx_errors {
- PD_TX_ERR_GOODCRC = -1, /* Failed to receive goodCRC */
- PD_TX_ERR_DISABLED = -2, /* Attempted transmit even though disabled */
- PD_TX_ERR_INV_ACK = -4, /* Received different packet instead of gCRC */
- PD_TX_ERR_COLLISION = -5 /* Collision detected during transmit */
-};
-
-/* PD Header with SOP* encoded in bits 31 - 28 */
-union pd_header_sop {
- uint16_t pd_header;
- uint32_t head;
-};
-
-/*
- * If TCPM is not on this chip, and PD low power is defined, then use low
- * power task delay logic.
- */
-#if !defined(CONFIG_USB_POWER_DELIVERY) && defined(CONFIG_USB_PD_LOW_POWER)
-#define TCPC_LOW_POWER
-#endif
-
-/*
- * Receive message buffer size. Buffer physical size is RX_BUFFER_SIZE + 1,
- * but only RX_BUFFER_SIZE of that memory is used to store messages that can
- * be retrieved from TCPM. The last slot is a temporary buffer for collecting
- * a message before deciding whether or not to keep it.
- */
-#ifdef CONFIG_USB_POWER_DELIVERY
-#define RX_BUFFER_SIZE 1
-#else
-#define RX_BUFFER_SIZE 2
-#endif
-
-static struct pd_port_controller {
- /* current port power role (SOURCE or SINK) */
- uint8_t power_role;
- /* current port data role (DFP or UFP) */
- uint8_t data_role;
- /* Port polarity : 0 => CC1 is CC line, 1 => CC2 is CC line */
- uint8_t polarity;
- /* Our CC pull resistor setting */
- uint8_t cc_pull;
- /* CC status */
- uint8_t cc_status[2];
- /* TCPC alert status */
- uint16_t alert;
- uint16_t alert_mask;
- /* RX enabled */
- uint8_t rx_enabled;
- /* Power status */
- uint8_t power_status;
- uint8_t power_status_mask;
-
-#ifdef TCPC_LOW_POWER
- /* Timestamp beyond which we allow low power task sampling */
- timestamp_t low_power_ts;
-#endif
-
- /* Last received */
- int rx_head[RX_BUFFER_SIZE+1];
- uint32_t rx_payload[RX_BUFFER_SIZE+1][7];
- int rx_buf_head, rx_buf_tail;
-
- /* Next transmit */
- enum tcpci_msg_type tx_type;
- uint16_t tx_head;
- uint32_t tx_payload[7];
- const uint32_t *tx_data;
-} pd[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-static int rx_buf_is_full(int port)
-{
- /*
- * TODO: Refactor these to use the incrementing-counter idiom instead of
- * the wrapping-counter idiom to reclaim the last buffer entry.
- *
- * Buffer is full if the tail is 1 ahead of head.
- */
- int diff = pd[port].rx_buf_tail - pd[port].rx_buf_head;
- return (diff == 1) || (diff == -RX_BUFFER_SIZE);
-}
-
-int rx_buf_is_empty(int port)
-{
- /* Buffer is empty if the head and tail are the same */
- return pd[port].rx_buf_tail == pd[port].rx_buf_head;
-}
-
-void rx_buf_clear(int port)
-{
- pd[port].rx_buf_tail = pd[port].rx_buf_head;
-}
-
-static void rx_buf_increment(int port, int *buf_ptr)
-{
- *buf_ptr = *buf_ptr == RX_BUFFER_SIZE ? 0 : *buf_ptr + 1;
-}
-
-static inline int encode_short(int port, int off, uint16_t val16)
-{
- off = pd_write_sym(port, off, bmc4b5b[(val16 >> 0) & 0xF]);
- off = pd_write_sym(port, off, bmc4b5b[(val16 >> 4) & 0xF]);
- off = pd_write_sym(port, off, bmc4b5b[(val16 >> 8) & 0xF]);
- return pd_write_sym(port, off, bmc4b5b[(val16 >> 12) & 0xF]);
-}
-
-int encode_word(int port, int off, uint32_t val32)
-{
- off = encode_short(port, off, (val32 >> 0) & 0xFFFF);
- return encode_short(port, off, (val32 >> 16) & 0xFFFF);
-}
-
-/* prepare a 4b/5b-encoded PD message to send */
-int prepare_message(int port, uint16_t header, uint8_t cnt,
- const uint32_t *data)
-{
- int off, i;
- /* 64-bit preamble */
- off = pd_write_preamble(port);
-#if defined(CONFIG_USB_VPD) || defined(CONFIG_USB_CTVPD)
- /* Start Of Packet Prime: 2x Sync-1 + 2x Sync-3 */
- off = pd_write_sym(port, off, BMC(PD_SYNC1));
- off = pd_write_sym(port, off, BMC(PD_SYNC1));
- off = pd_write_sym(port, off, BMC(PD_SYNC3));
- off = pd_write_sym(port, off, BMC(PD_SYNC3));
-#else
- /* Start Of Packet: 3x Sync-1 + 1x Sync-2 */
- off = pd_write_sym(port, off, BMC(PD_SYNC1));
- off = pd_write_sym(port, off, BMC(PD_SYNC1));
- off = pd_write_sym(port, off, BMC(PD_SYNC1));
- off = pd_write_sym(port, off, BMC(PD_SYNC2));
-#endif
- /* header */
- off = encode_short(port, off, header);
-
-#ifdef CONFIG_COMMON_RUNTIME
- mutex_lock(&pd_crc_lock);
-#endif
-
- crc32_init();
- crc32_hash16(header);
- /* data payload */
- for (i = 0; i < cnt; i++) {
- off = encode_word(port, off, data[i]);
- crc32_hash32(data[i]);
- }
- /* CRC */
- off = encode_word(port, off, crc32_result());
-
-#ifdef CONFIG_COMMON_RUNTIME
- mutex_unlock(&pd_crc_lock);
-#endif
-
- /* End Of Packet */
- off = pd_write_sym(port, off, BMC(PD_EOP));
- /* Ensure that we have a final edge */
- return pd_write_last_edge(port, off);
-}
-
-static int send_hard_reset(int port)
-{
- int off;
-
- if (debug_level >= 1)
- CPRINTF("C%d Send hard reset\n", port);
-
- /* 64-bit preamble */
- off = pd_write_preamble(port);
- /* Hard-Reset: 3x RST-1 + 1x RST-2 */
- off = pd_write_sym(port, off, BMC(PD_RST1));
- off = pd_write_sym(port, off, BMC(PD_RST1));
- off = pd_write_sym(port, off, BMC(PD_RST1));
- off = pd_write_sym(port, off, BMC(PD_RST2));
- /* Ensure that we have a final edge */
- off = pd_write_last_edge(port, off);
- /* Transmit the packet */
- if (pd_start_tx(port, pd[port].polarity, off) < 0)
- return PD_TX_ERR_COLLISION;
- pd_tx_done(port, pd[port].polarity);
- /* Keep RX monitoring on */
- pd_rx_enable_monitoring(port);
- return 0;
-}
-
-static int send_validate_message(int port, uint16_t header,
- const uint32_t *data)
-{
- int r;
- static uint32_t payload[7];
- uint8_t expected_msg_id = PD_HEADER_ID(header);
- uint8_t cnt = PD_HEADER_CNT(header);
- int retries = PD_HEADER_TYPE(header) == PD_DATA_SOURCE_CAP ?
- 0 :
- CONFIG_PD_RETRY_COUNT;
-
- /* retry 3 times if we are not getting a valid answer */
- for (r = 0; r <= retries; r++) {
- int bit_len, head;
- /* write the encoded packet in the transmission buffer */
- bit_len = prepare_message(port, header, cnt, data);
- /* Transmit the packet */
- if (pd_start_tx(port, pd[port].polarity, bit_len) < 0) {
- /*
- * Collision detected, return immediately so we can
- * respond to what we have received.
- */
- return PD_TX_ERR_COLLISION;
- }
- pd_tx_done(port, pd[port].polarity);
- /*
- * If this is the first attempt, leave RX monitoring off,
- * and do a blocking read of the channel until timeout or
- * packet received. If we failed the first try, enable
- * interrupt and yield to other tasks, so that we don't
- * starve them.
- */
- if (r) {
- pd_rx_enable_monitoring(port);
- /* Wait for message receive timeout */
- if (task_wait_event(USB_PD_RX_TMOUT_US) ==
- TASK_EVENT_TIMER)
- continue;
- /*
- * Make sure we woke up due to rx recd, otherwise
- * we need to manually start
- */
- if (!pd_rx_started(port)) {
- pd_rx_disable_monitoring(port);
- pd_rx_start(port);
- }
- } else {
- /* starting waiting for GoodCrc */
- pd_rx_start(port);
- }
- /* read the incoming packet if any */
- head = pd_analyze_rx(port, payload);
- pd_rx_complete(port);
- /* keep RX monitoring on to avoid collisions */
- pd_rx_enable_monitoring(port);
- if (head > 0) { /* we got a good packet, analyze it */
- int type = PD_HEADER_TYPE(head);
- int nb = PD_HEADER_CNT(head);
- uint8_t id = PD_HEADER_ID(head);
- if (type == PD_CTRL_GOOD_CRC && nb == 0 &&
- id == expected_msg_id) {
- /* got the GoodCRC we were expecting */
- /* do not catch last edges as a new packet */
- udelay(20);
- return bit_len;
- } else {
- /*
- * we have received a good packet
- * but not the expected GoodCRC,
- * the other side is trying to contact us,
- * bail out immediately so we can get the retry.
- */
- return PD_TX_ERR_INV_ACK;
- }
- }
- }
- /* we failed all the re-transmissions */
- if (debug_level >= 1)
- CPRINTF("TX NOACK%d %04x/%d\n", port, header, cnt);
- return PD_TX_ERR_GOODCRC;
-}
-
-static void send_goodcrc(int port, int id)
-{
- uint16_t header = PD_HEADER(PD_CTRL_GOOD_CRC, pd[port].power_role,
- pd[port].data_role, id, 0, 0, 0);
- int bit_len = prepare_message(port, header, 0, NULL);
-
- if (pd_start_tx(port, pd[port].polarity, bit_len) < 0)
- /* another packet recvd before we could send goodCRC */
- return;
- pd_tx_done(port, pd[port].polarity);
- /* Keep RX monitoring on */
- pd_rx_enable_monitoring(port);
-}
-
-#if 0
-/* TODO: when/how do we trigger this ? */
-static int analyze_rx_bist(int port);
-
-void bist_mode_2_rx(int port)
-{
- int analyze_bist = 0;
- int num_bits;
- timestamp_t start_time;
-
- /* monitor for incoming packet */
- pd_rx_enable_monitoring(port);
-
- /* loop until we start receiving data */
- start_time.val = get_time().val;
- while ((get_time().val - start_time.val) < (500*MSEC)) {
- task_wait_event(10*MSEC);
- /* incoming packet ? */
- if (pd_rx_started(port)) {
- analyze_bist = 1;
- break;
- }
- }
-
- if (analyze_bist) {
- /*
- * once we start receiving bist data, analyze 40 bytes
- * every 10 msec. Continue analyzing until BIST data
- * is no longer received. The standard limits the max
- * BIST length to 60 msec.
- */
- start_time.val = get_time().val;
- while ((get_time().val - start_time.val)
- < (PD_T_BIST_RECEIVE)) {
- num_bits = analyze_rx_bist(port);
- pd_rx_complete(port);
- /*
- * If no data was received, then analyze_rx_bist()
- * will return a -1 and there is no need to stay
- * in this mode
- */
- if (num_bits == -1)
- break;
- msleep(10);
- pd_rx_enable_monitoring(port);
- }
- } else {
- CPRINTF("BIST RX TO\n");
- }
-}
-#endif
-
-static void bist_mode_2_tx(int port)
-{
- int bit;
-
- CPRINTF("BIST 2: p%d\n", port);
- /*
- * build context buffer with 5 bytes, where the data is
- * alternating 1's and 0's.
- */
- bit = pd_write_sym(port, 0, BMC(0x15));
- bit = pd_write_sym(port, bit, BMC(0x0a));
- bit = pd_write_sym(port, bit, BMC(0x15));
- bit = pd_write_sym(port, bit, BMC(0x0a));
-
- /* start a circular DMA transfer */
- pd_tx_set_circular_mode(port);
- pd_start_tx(port, pd[port].polarity, bit);
-
- task_wait_event(PD_T_BIST_TRANSMIT);
-
- /* clear dma circular mode, will also stop dma */
- pd_tx_clear_circular_mode(port);
- /* finish and cleanup transmit */
- pd_tx_done(port, pd[port].polarity);
-}
-
-static inline int decode_short(int port, int off, uint16_t *val16)
-{
- uint32_t w;
- int end;
-
- end = pd_dequeue_bits(port, off, 20, &w);
-
-#if 0 /* DEBUG */
- CPRINTS("%d-%d: %05x %x:%x:%x:%x",
- off, end, w,
- dec4b5b[(w >> 15) & 0x1f], dec4b5b[(w >> 10) & 0x1f],
- dec4b5b[(w >> 5) & 0x1f], dec4b5b[(w >> 0) & 0x1f]);
-#endif
- *val16 = dec4b5b[w & 0x1f] |
- (dec4b5b[(w >> 5) & 0x1f] << 4) |
- (dec4b5b[(w >> 10) & 0x1f] << 8) |
- (dec4b5b[(w >> 15) & 0x1f] << 12);
- return end;
-}
-
-static inline int decode_word(int port, int off, uint32_t *val32)
-{
- off = decode_short(port, off, (uint16_t *)val32);
- return decode_short(port, off, ((uint16_t *)val32 + 1));
-}
-
-#ifdef CONFIG_COMMON_RUNTIME
-#if 0
-/*
- * TODO: when/how do we trigger this ? Could add custom vendor command
- * to TCPCI to enter bist verification? Is there an easier way?
- */
-static int count_set_bits(int n)
-{
- int count = 0;
- while (n) {
- n &= (n - 1);
- count++;
- }
- return count;
-}
-
-static int analyze_rx_bist(int port)
-{
- int i = 0, bit = -1;
- uint32_t w, match;
- int invalid_bits = 0;
- int bits_analyzed = 0;
- static int total_invalid_bits;
-
- /* dequeue bits until we see a full byte of alternating 1's and 0's */
- while (i < 10 && (bit < 0 || (w != 0xaa && w != 0x55)))
- bit = pd_dequeue_bits(port, i++, 8, &w);
-
- /* if we didn't find any bytes that match criteria, display error */
- if (i == 10) {
- CPRINTF("invalid pattern\n");
- return -1;
- }
- /*
- * now we know what matching byte we are looking for, dequeue a bunch
- * more data and count how many bits differ from expectations.
- */
- match = w;
- bit = i - 1;
- for (i = 0; i < 40; i++) {
- bit = pd_dequeue_bits(port, bit, 8, &w);
- if (i && (i % 20 == 0))
- CPRINTF("\n");
- CPRINTF("%02x ", w);
- bits_analyzed += 8;
- invalid_bits += count_set_bits(w ^ match);
- }
-
- total_invalid_bits += invalid_bits;
-
- CPRINTF("\nInvalid: %d/%d\n",
- invalid_bits, total_invalid_bits);
- return bits_analyzed;
-}
-#endif
-#endif
-
-int pd_analyze_rx(int port, uint32_t *payload)
-{
- int bit;
- char *msg = "---";
- uint32_t val = 0;
- union pd_header_sop phs;
- uint32_t pcrc, ccrc;
- int p, cnt;
- uint32_t eop;
-
- pd_init_dequeue(port);
-
- /* Detect preamble */
- bit = pd_find_preamble(port);
- if (bit == PD_RX_ERR_HARD_RESET || bit == PD_RX_ERR_CABLE_RESET) {
- /* Hard reset or cable reset */
- return bit;
- } else if (bit < 0) {
- msg = "Preamble";
- goto packet_err;
- }
-
- /* Find the Start Of Packet sequence */
- while (bit > 0) {
- bit = pd_dequeue_bits(port, bit, 20, &val);
-#if defined(CONFIG_USB_VPD) || defined(CONFIG_USB_CTVPD)
- if (val == PD_SOP_PRIME) {
- break;
- } else if (val == PD_SOP) {
- CPRINTF("SOP\n");
- return PD_RX_ERR_UNSUPPORTED_SOP;
- } else if (val == PD_SOP_PRIME_PRIME) {
- CPRINTF("SOP''\n");
- return PD_RX_ERR_UNSUPPORTED_SOP;
- }
-#else /* CONFIG_USB_VPD || CONFIG_USB_CTVPD */
-#ifdef CONFIG_USB_PD_DECODE_SOP
- if (val == PD_SOP || val == PD_SOP_PRIME ||
- val == PD_SOP_PRIME_PRIME)
- break;
-#else
- if (val == PD_SOP) {
- break;
- } else if (val == PD_SOP_PRIME) {
- CPRINTF("SOP'\n");
- return PD_RX_ERR_UNSUPPORTED_SOP;
- } else if (val == PD_SOP_PRIME_PRIME) {
- CPRINTF("SOP''\n");
- return PD_RX_ERR_UNSUPPORTED_SOP;
- }
-#endif /* CONFIG_USB_PD_DECODE_SOP */
-#endif /* CONFIG_USB_VPD || CONFIG_USB_CTVPD */
- }
- if (bit < 0) {
-#ifdef CONFIG_USB_PD_DECODE_SOP
- if (val == PD_SOP)
- msg = "SOP";
- else if (val == PD_SOP_PRIME)
- msg = "SOP'";
- else if (val == PD_SOP_PRIME_PRIME)
- msg = "SOP''";
- else
- msg = "SOP*";
-#else
- msg = "SOP";
-#endif
- goto packet_err;
- }
-
- phs.head = 0;
-
- /* read header */
- bit = decode_short(port, bit, &phs.pd_header);
-
-#ifdef CONFIG_COMMON_RUNTIME
- mutex_lock(&pd_crc_lock);
-#endif
-
- crc32_init();
- crc32_hash16(phs.pd_header);
- cnt = PD_HEADER_CNT(phs.pd_header);
-
-#ifdef CONFIG_USB_PD_DECODE_SOP
- /* Encode message address */
- if (val == PD_SOP) {
- phs.head |= PD_HEADER_SOP(TCPCI_MSG_SOP);
- } else if (val == PD_SOP_PRIME) {
- phs.head |= PD_HEADER_SOP(TCPCI_MSG_SOP_PRIME);
- } else if (val == PD_SOP_PRIME_PRIME) {
- phs.head |= PD_HEADER_SOP(TCPCI_MSG_SOP_PRIME_PRIME);
- } else {
- msg = "SOP*";
- goto packet_err;
- }
-#endif
-
- /* read payload data */
- for (p = 0; p < cnt && bit > 0; p++) {
- bit = decode_word(port, bit, payload+p);
- crc32_hash32(payload[p]);
- }
- ccrc = crc32_result();
-
-#ifdef CONFIG_COMMON_RUNTIME
- mutex_unlock(&pd_crc_lock);
-#endif
-
- if (bit < 0) {
- msg = "len";
- goto packet_err;
- }
-
- /* check transmitted CRC */
- bit = decode_word(port, bit, &pcrc);
- if (bit < 0 || pcrc != ccrc) {
- msg = "CRC";
- if (pcrc != ccrc)
- bit = PD_RX_ERR_CRC;
- if (debug_level >= 1)
- CPRINTF("CRC%d %08x <> %08x\n", port, pcrc, ccrc);
- goto packet_err;
- }
-
- /*
- * Check EOP. EOP is 5 bits, but last bit may not be able to
- * be dequeued, depending on ending state of CC line, so stop
- * at 4 bits (assumes last bit is 0).
- */
- bit = pd_dequeue_bits(port, bit, 4, &eop);
- if (bit < 0 || eop != PD_EOP) {
- msg = "EOP";
- goto packet_err;
- }
-
- return phs.head;
-packet_err:
- if (debug_level >= 2)
- pd_dump_packet(port, msg);
- else
- CPRINTF("RXERR%d %s\n", port, msg);
- return bit;
-}
-
-static void handle_request(int port, uint16_t head)
-{
- int cnt = PD_HEADER_CNT(head);
-
- if (PD_HEADER_TYPE(head) != PD_CTRL_GOOD_CRC || cnt)
- send_goodcrc(port, PD_HEADER_ID(head));
- else
- /* keep RX monitoring on to avoid collisions */
- pd_rx_enable_monitoring(port);
-}
-
-/* Convert CC voltage to CC status */
-static int cc_voltage_to_status(int port, int cc_volt, int cc_sel)
-{
- /* If we have a pull-up, then we are source, check for Rd. */
- if (pd[port].cc_pull == TYPEC_CC_RP) {
- if (CC_NC(port, cc_volt, cc_sel))
- return TYPEC_CC_VOLT_OPEN;
- else if (CC_RA(port, cc_volt, cc_sel))
- return TYPEC_CC_VOLT_RA;
- else
- return TYPEC_CC_VOLT_RD;
- /* If we have a pull-down, then we are sink, check for Rp. */
- }
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- else if (pd[port].cc_pull == TYPEC_CC_RD) {
- if (cc_volt >= TYPE_C_SRC_3000_THRESHOLD)
- return TYPEC_CC_VOLT_RP_3_0;
- else if (cc_volt >= TYPE_C_SRC_1500_THRESHOLD)
- return TYPEC_CC_VOLT_RP_1_5;
- else if (CC_RP(cc_volt))
- return TYPEC_CC_VOLT_RP_DEF;
- else
- return TYPEC_CC_VOLT_OPEN;
- }
-#endif
- /* If we are open, then always return 0 */
- else
- return 0;
-}
-
-static void alert(int port, int mask)
-{
- /* Always update the Alert status register */
- pd[port].alert |= mask;
- /*
- * Only send interrupt to TCPM if corresponding
- * bit in the alert_enable register is set.
- */
- if (pd[port].alert_mask & mask)
- tcpc_alert(port);
-}
-
-int tcpc_run(int port, int evt)
-{
- int cc, i, res;
-
- /* Don't do anything when port is not available */
- if (port >= board_get_usb_pd_port_count())
- return -1;
-
- /* incoming packet ? */
- if (pd_rx_started(port) && pd[port].rx_enabled) {
- /* Get message and place at RX buffer head */
- res = pd[port].rx_head[pd[port].rx_buf_head] =
- pd_analyze_rx(port,
- pd[port].rx_payload[pd[port].rx_buf_head]);
- pd_rx_complete(port);
-
- /*
- * If there is space in buffer, then increment head to keep
- * the message and send goodCRC. If this is a hard reset,
- * send alert regardless of rx buffer status. Else if there is
- * no space in buffer, then do not send goodCRC and drop
- * message.
- */
- if (res > 0 && !rx_buf_is_full(port)) {
- rx_buf_increment(port, &pd[port].rx_buf_head);
- handle_request(port, res);
- alert(port, TCPC_REG_ALERT_RX_STATUS);
- } else if (res == PD_RX_ERR_HARD_RESET) {
- alert(port, TCPC_REG_ALERT_RX_HARD_RST);
- }
- }
-
- /* outgoing packet ? */
- if ((evt & PD_EVENT_TX) && pd[port].rx_enabled) {
- switch (pd[port].tx_type) {
-#if defined(CONFIG_USB_VPD) || defined(CONFIG_USB_CTVPD)
- case TCPCI_MSG_SOP_PRIME:
-#else
- case TCPCI_MSG_SOP:
-#endif
- res = send_validate_message(port,
- pd[port].tx_head,
- pd[port].tx_data);
- break;
- case TCPCI_MSG_TX_BIST_MODE_2:
- bist_mode_2_tx(port);
- res = 0;
- break;
- case TCPCI_MSG_TX_HARD_RESET:
- res = send_hard_reset(port);
- break;
- default:
- res = PD_TX_ERR_DISABLED;
- break;
- }
-
- /* send appropriate alert for tx completion */
- if (res >= 0)
- alert(port, TCPC_REG_ALERT_TX_SUCCESS);
- else if (res == PD_TX_ERR_GOODCRC)
- alert(port, TCPC_REG_ALERT_TX_FAILED);
- else
- alert(port, TCPC_REG_ALERT_TX_DISCARDED);
- } else {
- /* If we have nothing to transmit, then sample CC lines */
-
- /* CC pull changed, wait 1ms for CC voltage to stabilize */
- if (evt & PD_EVENT_CC)
- usleep(MSEC);
-
- /* check CC lines */
- for (i = 0; i < 2; i++) {
- /* read CC voltage */
- cc = pd_adc_read(port, i);
-
- /* convert voltage to status, and check status change */
- cc = cc_voltage_to_status(port, cc, i);
- if (pd[port].cc_status[i] != cc) {
- pd[port].cc_status[i] = cc;
- alert(port, TCPC_REG_ALERT_CC_STATUS);
- }
- }
- }
-
- /* make sure PD monitoring is enabled to wake on PD RX */
- if (pd[port].rx_enabled)
- pd_rx_enable_monitoring(port);
-
-#ifdef TCPC_LOW_POWER
- /*
- * If we are presenting Rd with no connection, and timestamp is
- * past the low power timestamp, then we don't need to sample
- * CC lines as often. In this case, our connection delay should not
- * actually increased because we will get an interrupt on VBUS detect.
- */
- return (get_time().val >= pd[port].low_power_ts.val &&
- pd[port].cc_pull == TYPEC_CC_RD &&
- cc_is_open(pd[port].cc_status[0], pd[port].cc_status[1]))
- ? 200 * MSEC
- : 10 * MSEC;
-#else
- return 10*MSEC;
-#endif
-}
-
-#if !defined(CONFIG_USB_POWER_DELIVERY)
-void pd_task(void *u)
-{
- int port = TASK_ID_TO_PD_PORT(task_get_current());
- int timeout = 10*MSEC;
- int evt;
-
- /* initialize phy task */
- tcpc_init(port);
-
- /* we are now initialized */
- pd[port].power_status &= ~TCPC_REG_POWER_STATUS_UNINIT;
-
- while (1) {
- /* wait for next event/packet or timeout expiration */
- evt = task_wait_event(timeout);
-
- /* run phy task once */
- timeout = tcpc_run(port, evt);
- }
-}
-#endif
-
-void pd_rx_event(int port)
-{
- task_set_event(PD_PORT_TO_TASK_ID(port), TASK_EVENT_WAKE);
-}
-
-int tcpc_alert_status(int port, int *alert)
-{
- /* return the value of the TCPC Alert register */
- uint16_t ret = pd[port].alert;
- *alert = ret;
- return EC_SUCCESS;
-}
-
-int tcpc_alert_status_clear(int port, uint16_t mask)
-{
- /*
- * If the RX status alert is attempting to be cleared, then increment
- * rx buffer tail pointer. if the RX buffer is not empty, then keep
- * the RX status alert active.
- */
- if (mask & TCPC_REG_ALERT_RX_STATUS) {
- if (!rx_buf_is_empty(port)) {
- rx_buf_increment(port, &pd[port].rx_buf_tail);
- if (!rx_buf_is_empty(port))
- /* buffer is not empty, keep alert active */
- mask &= ~TCPC_REG_ALERT_RX_STATUS;
- }
- }
-
- /* clear only the bits specified by the TCPM */
- pd[port].alert &= ~mask;
-#ifndef CONFIG_USB_POWER_DELIVERY
- /* Set Alert# inactive if all alert bits clear */
- if (!pd[port].alert)
- tcpc_alert_clear(port);
-#endif
- return EC_SUCCESS;
-}
-
-int tcpc_alert_mask_set(int port, uint16_t mask)
-{
- /* Update the alert mask as specificied by the TCPM */
- pd[port].alert_mask = mask;
- return EC_SUCCESS;
-}
-
-int tcpc_set_cc(int port, int pull)
-{
- /* If CC pull resistor not changing, then nothing to do */
- if (pd[port].cc_pull == pull)
- return EC_SUCCESS;
-
- /* Change CC pull resistor */
- pd[port].cc_pull = pull;
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- pd_set_host_mode(port, pull == TYPEC_CC_RP);
-#endif
-
-#ifdef TCPC_LOW_POWER
- /*
- * Reset the low power timestamp every time CC termination toggles,
- * because we only want to go into low power mode when we are not
- * dual-role toggling.
- */
- pd[port].low_power_ts.val = get_time().val +
- 2*(PD_T_DRP_SRC + PD_T_DRP_SNK);
-#endif
-
- /*
- * Before CC pull can be changed and the task can read the new
- * status, we should set the CC status to open, in case TCPM
- * asks before it is known for sure.
- */
- pd[port].cc_status[0] = TYPEC_CC_VOLT_OPEN;
- pd[port].cc_status[1] = pd[port].cc_status[0];
-
- /* Wake the PD phy task with special CC event mask */
- /* TODO: use top case if no TCPM on same CPU */
-#ifdef CONFIG_USB_POWER_DELIVERY
- tcpc_run(port, PD_EVENT_CC);
-#else
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC);
-#endif
- return EC_SUCCESS;
-}
-
-int tcpc_get_cc(int port, enum tcpc_cc_voltage_status *cc1,
- enum tcpc_cc_voltage_status *cc2)
-{
- *cc2 = pd[port].cc_status[1];
- *cc1 = pd[port].cc_status[0];
-
- return EC_SUCCESS;
-}
-
-int board_select_rp_value(int port, int rp) __attribute__((weak));
-
-int tcpc_select_rp_value(int port, int rp)
-{
- if (board_select_rp_value)
- return board_select_rp_value(port, rp);
- else
- return EC_ERROR_UNIMPLEMENTED;
-}
-
-int tcpc_set_polarity(int port, int polarity)
-{
- pd[port].polarity = polarity;
- pd_select_polarity(port, pd[port].polarity);
-
- return EC_SUCCESS;
-}
-
-#ifdef CONFIG_USB_PD_TCPC_TRACK_VBUS
-static int tcpc_set_power_status(int port, int vbus_present)
-{
- /* Update VBUS present bit */
- if (vbus_present)
- pd[port].power_status |= TCPC_REG_POWER_STATUS_VBUS_PRES;
- else
- pd[port].power_status &= ~TCPC_REG_POWER_STATUS_VBUS_PRES;
-
- /* Set bit Port Power Status bit in Alert register */
- if (pd[port].power_status_mask & TCPC_REG_POWER_STATUS_VBUS_PRES)
- alert(port, TCPC_REG_ALERT_POWER_STATUS);
-
- return EC_SUCCESS;
-}
-#endif /* CONFIG_USB_PD_TCPC_TRACK_VBUS */
-
-int tcpc_set_power_status_mask(int port, uint8_t mask)
-{
- pd[port].power_status_mask = mask;
- return EC_SUCCESS;
-}
-
-int tcpc_set_vconn(int port, int enable)
-{
-#ifdef CONFIG_USBC_VCONN
- pd_set_vconn(port, pd[port].polarity, enable);
-#endif
- return EC_SUCCESS;
-}
-
-int tcpc_set_rx_enable(int port, int enable)
-{
-#if defined(CONFIG_LOW_POWER_IDLE) && !defined(CONFIG_USB_POWER_DELIVERY)
- int i;
-#endif
- pd[port].rx_enabled = enable;
-
- if (!enable)
- pd_rx_disable_monitoring(port);
-
-#if defined(CONFIG_LOW_POWER_IDLE) && !defined(CONFIG_USB_POWER_DELIVERY)
- /* If any PD port is connected, then disable deep sleep */
- for (i = 0; i < board_get_usb_pd_port_count(); ++i)
- if (pd[i].rx_enabled)
- break;
-
- if (i == board_get_usb_pd_port_count())
- enable_sleep(SLEEP_MASK_USB_PD);
- else
- disable_sleep(SLEEP_MASK_USB_PD);
-#endif
- return EC_SUCCESS;
-}
-
-int tcpc_transmit(int port, enum tcpci_msg_type type, uint16_t header,
- const uint32_t *data)
-{
- /* Store data to transmit and wake task to send it */
- pd[port].tx_type = type;
- pd[port].tx_head = header;
- pd[port].tx_data = data;
- /* TODO: use top case if no TCPM on same CPU */
-#ifdef CONFIG_USB_POWER_DELIVERY
- tcpc_run(port, PD_EVENT_TX);
-#else
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TX);
-#endif
- return EC_SUCCESS;
-}
-
-int tcpc_set_msg_header(int port, int power_role, int data_role)
-{
- pd[port].power_role = power_role;
- pd[port].data_role = data_role;
-
- return EC_SUCCESS;
-}
-
-int tcpc_get_message(int port, uint32_t *payload, int *head)
-{
- /* Get message at tail of RX buffer */
- int idx = pd[port].rx_buf_tail;
-
- memcpy(payload, pd[port].rx_payload[idx],
- sizeof(pd[port].rx_payload[idx]));
- *head = pd[port].rx_head[idx];
- return EC_SUCCESS;
-}
-
-void tcpc_pre_init(void)
-{
- int i;
-
- /* Mark as uninitialized */
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- pd[i].power_status |= TCPC_REG_POWER_STATUS_UNINIT |
- TCPC_REG_POWER_STATUS_VBUS_DET;
-}
-/* Must be prioritized above i2c init */
-DECLARE_HOOK(HOOK_INIT, tcpc_pre_init, HOOK_PRIO_INIT_I2C - 1);
-
-void tcpc_init(int port)
-{
- int i;
-
- if (port >= board_get_usb_pd_port_count())
- return;
-
- /* Initialize physical layer */
- pd_hw_init(port, PD_ROLE_DEFAULT(port));
- pd[port].cc_pull = PD_ROLE_DEFAULT(port) ==
- PD_ROLE_SOURCE ? TYPEC_CC_RP : TYPEC_CC_RD;
-#ifdef TCPC_LOW_POWER
- /* Don't use low power immediately after boot */
- pd[port].low_power_ts.val = get_time().val + SECOND;
-#endif
-
- /* make sure PD monitoring is disabled initially */
- pd[port].rx_enabled = 0;
-
- /* make initial readings of CC voltages */
- for (i = 0; i < 2; i++) {
- pd[port].cc_status[i] = cc_voltage_to_status(port,
- pd_adc_read(port, i),
- i);
- }
-
-#ifdef CONFIG_USB_PD_TCPC_TRACK_VBUS
-#if CONFIG_USB_PD_PORT_MAX_COUNT >= 2
- tcpc_set_power_status(port, !gpio_get_level(port ?
- GPIO_USB_C1_VBUS_WAKE_L :
- GPIO_USB_C0_VBUS_WAKE_L));
-#else
- tcpc_set_power_status(port, !gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L));
-#endif /* CONFIG_USB_PD_PORT_MAX_COUNT >= 2 */
-#endif /* CONFIG_USB_PD_TCPC_TRACK_VBUS */
-
- /* set default alert and power mask register values */
- pd[port].alert_mask = TCPC_REG_ALERT_MASK_ALL;
- pd[port].power_status_mask = TCPC_REG_POWER_STATUS_MASK_ALL;
-
- /* set power status alert since the UNINIT bit has been set */
- alert(port, TCPC_REG_ALERT_POWER_STATUS);
-}
-
-#ifdef CONFIG_USB_PD_TCPC_TRACK_VBUS
-void pd_vbus_evt_p0(enum gpio_signal signal)
-{
- tcpc_set_power_status(TASK_ID_TO_PD_PORT(TASK_ID_PD_C0),
- !gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L));
- task_wake(TASK_ID_PD_C0);
-}
-
-#if CONFIG_USB_PD_PORT_MAX_COUNT >= 2
-void pd_vbus_evt_p1(enum gpio_signal signal)
-{
- if (board_get_usb_pd_port_count() == 1)
- return;
-
- tcpc_set_power_status(TASK_ID_TO_PD_PORT(TASK_ID_PD_C1),
- !gpio_get_level(GPIO_USB_C1_VBUS_WAKE_L));
- task_wake(TASK_ID_PD_C1);
-}
-#endif /* PD_PORT_COUNT >= 2 */
-#endif /* CONFIG_USB_PD_TCPC_TRACK_VBUS */
-
-#ifndef CONFIG_USB_POWER_DELIVERY
-static void tcpc_i2c_write(int port, int reg, int len, uint8_t *payload)
-{
- uint16_t alert;
-
- /* If we are not yet initialized, ignore any write command */
- if (pd[port].power_status & TCPC_REG_POWER_STATUS_UNINIT)
- return;
-
- switch (reg) {
- case TCPC_REG_ROLE_CTRL:
- tcpc_set_cc(port, TCPC_REG_ROLE_CTRL_CC1(payload[1]));
- break;
- case TCPC_REG_POWER_CTRL:
- tcpc_set_vconn(port, TCPC_REG_POWER_CTRL_VCONN(payload[1]));
- break;
- case TCPC_REG_TCPC_CTRL:
- tcpc_set_polarity(port,
- TCPC_REG_TCPC_CTRL_POLARITY(payload[1]));
- break;
- case TCPC_REG_MSG_HDR_INFO:
- tcpc_set_msg_header(port,
- TCPC_REG_MSG_HDR_INFO_PROLE(payload[1]),
- TCPC_REG_MSG_HDR_INFO_DROLE(payload[1]));
- break;
- case TCPC_REG_ALERT:
- alert = payload[1];
- alert |= (payload[2] << 8);
- /* clear alert bits specified by the TCPM */
- tcpc_alert_status_clear(port, alert);
- break;
- case TCPC_REG_ALERT_MASK:
- alert = payload[1];
- alert |= (payload[2] << 8);
- tcpc_alert_mask_set(port, alert);
- break;
- case TCPC_REG_RX_DETECT:
- tcpc_set_rx_enable(port, payload[1] &
- TCPC_REG_RX_DETECT_SOP_HRST_MASK);
- break;
- case TCPC_REG_POWER_STATUS_MASK:
- tcpc_set_power_status_mask(port, payload[1]);
- break;
- case TCPC_REG_TX_HDR:
- pd[port].tx_head = (payload[2] << 8) | payload[1];
- break;
- case TCPC_REG_TX_DATA:
- memcpy(pd[port].tx_payload, &payload[1], len - 1);
- break;
- case TCPC_REG_TRANSMIT:
- tcpc_transmit(port, TCPC_REG_TRANSMIT_TYPE(payload[1]),
- pd[port].tx_head, pd[port].tx_payload);
- break;
- }
-}
-
-static int tcpc_i2c_read(int port, int reg, uint8_t *payload)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
- int alert;
-
- switch (reg) {
- case TCPC_REG_VENDOR_ID:
- *(uint16_t *)payload = USB_VID_GOOGLE;
- return 2;
- case TCPC_REG_CC_STATUS:
- tcpc_get_cc(port, &cc1, &cc2);
- payload[0] = TCPC_REG_CC_STATUS_SET(
- pd[port].cc_pull == TYPEC_CC_RD,
- pd[port].cc_status[0], pd[port].cc_status[1]);
- return 1;
- case TCPC_REG_ROLE_CTRL:
- payload[0] = TCPC_REG_ROLE_CTRL_SET(0, 0,
- pd[port].cc_pull,
- pd[port].cc_pull);
- return 1;
- case TCPC_REG_TCPC_CTRL:
- payload[0] = TCPC_REG_TCPC_CTRL_SET(pd[port].polarity);
- return 1;
- case TCPC_REG_MSG_HDR_INFO:
- payload[0] = TCPC_REG_MSG_HDR_INFO_SET(pd[port].data_role,
- pd[port].power_role);
- return 1;
- case TCPC_REG_RX_DETECT:
- payload[0] = pd[port].rx_enabled ?
- TCPC_REG_RX_DETECT_SOP_HRST_MASK : 0;
- return 1;
- case TCPC_REG_ALERT:
- tcpc_alert_status(port, &alert);
- payload[0] = alert & 0xff;
- payload[1] = (alert >> 8) & 0xff;
- return 2;
- case TCPC_REG_ALERT_MASK:
- payload[0] = pd[port].alert_mask & 0xff;
- payload[1] = (pd[port].alert_mask >> 8) & 0xff;
- return 2;
- case TCPC_REG_RX_BYTE_CNT:
- payload[0] = 3 + 4 *
- PD_HEADER_CNT(pd[port].rx_head[pd[port].rx_buf_tail]);
- return 1;
- case TCPC_REG_RX_HDR:
- payload[0] = pd[port].rx_head[pd[port].rx_buf_tail] & 0xff;
- payload[1] =
- (pd[port].rx_head[pd[port].rx_buf_tail] >> 8) & 0xff;
- return 2;
- case TCPC_REG_RX_DATA:
- memcpy(payload, pd[port].rx_payload[pd[port].rx_buf_tail],
- sizeof(pd[port].rx_payload[pd[port].rx_buf_tail]));
- return sizeof(pd[port].rx_payload[pd[port].rx_buf_tail]);
- case TCPC_REG_POWER_STATUS:
- payload[0] = pd[port].power_status;
- return 1;
- case TCPC_REG_POWER_STATUS_MASK:
- payload[0] = pd[port].power_status_mask;
- return 1;
- case TCPC_REG_TX_HDR:
- payload[0] = pd[port].tx_head & 0xff;
- payload[1] = (pd[port].tx_head >> 8) & 0xff;
- return 2;
- case TCPC_REG_TX_DATA:
- memcpy(payload, pd[port].tx_payload,
- sizeof(pd[port].tx_payload));
- return sizeof(pd[port].tx_payload);
- default:
- return 0;
- }
-}
-
-void tcpc_i2c_process(int read, int port, int len, uint8_t *payload,
- void (*send_response)(int))
-{
- int i, reg;
-
- if (debug_level >= 1) {
- CPRINTF("tcpci p%d: ", port);
- for (i = 0; i < len; i++)
- CPRINTF("0x%02x ", payload[i]);
- CPRINTF("\n");
- }
-
- /* length must always be at least 1 */
- if (len == 0) {
- /*
- * if this is a read, we must call send_response() for
- * i2c transaction to finishe properly
- */
- if (read)
- (*send_response)(0);
- }
-
- /* if this is a write, length must be at least 2 */
- if (!read && len < 2)
- return;
-
- /* register is always first byte */
- reg = payload[0];
-
- /* perform read or write */
- if (read) {
- len = tcpc_i2c_read(port, reg, payload);
- (*send_response)(len);
- } else {
- tcpc_i2c_write(port, reg, len, payload);
- }
-}
-#endif
-
-#ifdef CONFIG_COMMON_RUNTIME
-static int command_tcpc(int argc, char **argv)
-{
- int port;
- char *e;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- if (!strcasecmp(argv[1], "dump")) {
- int level;
-
- if (argc < 3)
- ccprintf("lvl: %d\n", debug_level);
- else {
- level = strtoi(argv[2], &e, 10);
- if (*e)
- return EC_ERROR_PARAM2;
- debug_level = level;
- }
- return EC_SUCCESS;
- }
-
- /* command: pd <port> <subcmd> [args] */
- port = strtoi(argv[1], &e, 10);
- if (argc < 3)
- return EC_ERROR_PARAM_COUNT;
- if (*e || port >= board_get_usb_pd_port_count())
- return EC_ERROR_PARAM2;
-
- if (!strcasecmp(argv[2], "clock")) {
- int freq;
-
- if (argc < 4)
- return EC_ERROR_PARAM2;
-
- freq = strtoi(argv[3], &e, 10);
- if (*e)
- return EC_ERROR_PARAM2;
- pd_set_clock(port, freq);
- ccprintf("set TX frequency to %d Hz\n", freq);
- return EC_SUCCESS;
- } else if (!strncasecmp(argv[2], "state", 5)) {
- ccprintf("Port C%d, %s - CC:%d, CC0:%d, CC1:%d\n"
- "Alert: 0x%02x Mask: 0x%04x\n"
- "Power Status: 0x%02x Mask: 0x%02x\n", port,
- pd[port].rx_enabled ? "Ena" : "Dis",
- pd[port].cc_pull,
- pd[port].cc_status[0], pd[port].cc_status[1],
- pd[port].alert, pd[port].alert_mask,
- pd[port].power_status, pd[port].power_status_mask);
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(tcpc, command_tcpc,
- "dump [0|1]\n\t<port> [clock|state]",
- "Type-C Port Controller");
-#endif
diff --git a/common/usb_port_power_dumb.c b/common/usb_port_power_dumb.c
deleted file mode 100644
index 09c7e29033..0000000000
--- a/common/usb_port_power_dumb.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/* Copyright 2012 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.
- */
-
-/* USB charging control module for Chrome EC */
-
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "system.h"
-#include "usb_charge.h"
-#include "util.h"
-
-#define CPUTS(outstr) cputs(CC_USBCHARGE, outstr)
-#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
-
-static uint8_t charge_mode[USB_PORT_COUNT];
-
-static void usb_port_set_enabled(int port_id, int en)
-{
- gpio_set_level(usb_port_enable[port_id], en);
- charge_mode[port_id] = en;
-}
-
-__maybe_unused static void usb_port_all_ports_on(void)
-{
- int i;
- for (i = 0; i < USB_PORT_COUNT; i++)
- usb_port_set_enabled(i, 1);
-}
-
-static void usb_port_all_ports_off(void)
-{
- int i;
- for (i = 0; i < USB_PORT_COUNT; i++)
- usb_port_set_enabled(i, 0);
-}
-
-/*****************************************************************************/
-/* Host commands */
-
-int usb_charge_set_mode(int port_id, enum usb_charge_mode mode,
- enum usb_suspend_charge inhibit_charge)
-{
- CPRINTS("USB port p%d %d", port_id, mode);
-
- if (port_id < 0 || port_id >= USB_PORT_COUNT)
- return EC_ERROR_INVAL;
-
- switch (mode) {
- case USB_CHARGE_MODE_DISABLED:
- usb_port_set_enabled(port_id, 0);
- break;
- case USB_CHARGE_MODE_ENABLED:
- usb_port_set_enabled(port_id, 1);
- break;
- default:
- return EC_ERROR_UNKNOWN;
- }
-
- return EC_SUCCESS;
-}
-
-static enum ec_status
-usb_port_command_set_mode(struct host_cmd_handler_args *args)
-{
- const struct ec_params_usb_charge_set_mode *p = args->params;
-
- if (usb_charge_set_mode(p->usb_port_id, p->mode,
- p->inhibit_charge) != EC_SUCCESS)
- return EC_RES_ERROR;
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_CHARGE_SET_MODE,
- usb_port_command_set_mode,
- EC_VER_MASK(0));
-
-/*****************************************************************************/
-/* Console commands */
-
-static int command_set_mode(int argc, char **argv)
-{
- int port_id = -1;
- int mode = -1;
- int i;
- char *e;
-
- switch (argc) {
- case 3:
- port_id = strtoi(argv[1], &e, 0);
- if (*e || port_id < 0 || port_id >= USB_PORT_COUNT)
- return EC_ERROR_PARAM1;
-
- if (!parse_bool(argv[2], &mode))
- return EC_ERROR_PARAM2;
-
- usb_port_set_enabled(port_id, mode);
- /* fallthrough */
- case 1:
- for (i = 0; i < USB_PORT_COUNT; i++)
- ccprintf("Port %d: %s\n",
- i, charge_mode[i] ? "on" : "off");
- return EC_SUCCESS;
- }
-
- return EC_ERROR_PARAM_COUNT;
-}
-DECLARE_CONSOLE_COMMAND(usbchargemode, command_set_mode,
- "[<port> <on | off>]",
- "Set USB charge mode");
-
-
-/*****************************************************************************/
-/* Hooks */
-
-static void usb_port_preserve_state(void)
-{
- system_add_jump_tag(USB_SYSJUMP_TAG, USB_HOOK_VERSION,
- sizeof(charge_mode), charge_mode);
-}
-DECLARE_HOOK(HOOK_SYSJUMP, usb_port_preserve_state, HOOK_PRIO_DEFAULT);
-
-static void usb_port_init(void)
-{
- const uint8_t *prev;
- int version, size, i;
-
- prev = (const uint8_t *)system_get_jump_tag(USB_SYSJUMP_TAG,
- &version, &size);
- if (!prev || version != USB_HOOK_VERSION ||
- size != sizeof(charge_mode)) {
- usb_port_all_ports_off();
- return;
- }
-
- for (i = 0; i < USB_PORT_COUNT; i++)
- usb_port_set_enabled(i, prev[i]);
-}
-DECLARE_HOOK(HOOK_INIT, usb_port_init, HOOK_PRIO_DEFAULT);
-
-#ifndef CONFIG_USB_PORT_POWER_DUMB_CUSTOM_HOOK
-static void usb_port_startup(void)
-{
- /* Turn on USB ports on as we go into S0 from S5. */
- usb_port_all_ports_on();
-}
-DECLARE_HOOK(HOOK_CHIPSET_STARTUP, usb_port_startup, HOOK_PRIO_DEFAULT);
-
-static void usb_port_shutdown(void)
-{
- /* Turn on USB ports off as we go back to S5. */
- usb_port_all_ports_off();
-}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, usb_port_shutdown, HOOK_PRIO_DEFAULT);
-#endif /* CONFIG_USB_PORT_POWER_DUMB_CUSTOM_HOOK */
diff --git a/common/usb_port_power_smart.c b/common/usb_port_power_smart.c
deleted file mode 100644
index 170180cbab..0000000000
--- a/common/usb_port_power_smart.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/* Copyright 2012 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.
- */
-
-/* USB charging control module for Chrome EC */
-
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "system.h"
-#include "usb_charge.h"
-#include "util.h"
-
-#define CPUTS(outstr) cputs(CC_USBCHARGE, outstr)
-#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
-
-#ifndef CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE
-#define CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE USB_CHARGE_MODE_SDP2
-#endif
-
-struct charge_mode_t {
- uint8_t mode:7;
- uint8_t inhibit_charging_in_suspend:1;
-} __pack;
-
-static struct charge_mode_t charge_mode[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT];
-
-#ifdef CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY
-/*
- * If we only support CDP and SDP, the control signals are hard-wired so
- * there's nothing to do. The only to do is set ILIM_SEL.
- */
-static void usb_charge_set_control_mode(int port_id, int mode) {}
-#else /* !defined(CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY) */
-static void usb_charge_set_control_mode(int port_id, int mode)
-{
-#ifdef CONFIG_USB_PORT_POWER_SMART_SIMPLE
- /*
- * One single shared control signal, so the last mode set to either
- * port wins. Also, only CTL1 can be set; the other pins are
- * hard-wired.
- */
- gpio_or_ioex_set_level(GPIO_USB_CTL1, mode & 0x4);
-#else
- if (port_id == 0) {
- gpio_or_ioex_set_level(GPIO_USB1_CTL1, mode & 0x4);
- gpio_or_ioex_set_level(GPIO_USB1_CTL2, mode & 0x2);
- gpio_or_ioex_set_level(GPIO_USB1_CTL3, mode & 0x1);
- } else {
- gpio_or_ioex_set_level(GPIO_USB2_CTL1, mode & 0x4);
- gpio_or_ioex_set_level(GPIO_USB2_CTL2, mode & 0x2);
- gpio_or_ioex_set_level(GPIO_USB2_CTL3, mode & 0x1);
- }
-#endif /* defined(CONFIG_USB_PORT_POWER_SMART_SIMPLE) */
-}
-#endif /* defined(CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY) */
-
-static void usb_charge_set_enabled(int port_id, int en)
-{
- ASSERT(port_id < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT);
- gpio_or_ioex_set_level(usb_port_enable[port_id], en);
-}
-
-static void usb_charge_set_ilim(int port_id, int sel)
-{
- int ilim_sel;
-
-#if defined(CONFIG_USB_PORT_POWER_SMART_SIMPLE) || \
- defined(CONFIG_USB_PORT_POWER_SMART_INVERTED)
- /* ILIM_SEL is inverted. */
- sel = !sel;
-#endif
-
- ilim_sel = GPIO_USB1_ILIM_SEL;
-#if !defined(CONFIG_USB_PORT_POWER_SMART_SIMPLE) && \
- CONFIG_USB_PORT_POWER_SMART_PORT_COUNT == 2
- if (port_id != 0)
- ilim_sel = GPIO_USB2_ILIM_SEL;
-#endif
-
- gpio_or_ioex_set_level(ilim_sel, sel);
-}
-
-static void usb_charge_all_ports_ctrl(enum usb_charge_mode mode)
-{
- int i;
-
- for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++)
- usb_charge_set_mode(i, mode, USB_ALLOW_SUSPEND_CHARGE);
-}
-
-int usb_charge_set_mode(int port_id, enum usb_charge_mode mode,
- enum usb_suspend_charge inhibit_charge)
-{
- CPRINTS("USB charge p%d m%d i%d", port_id, mode, inhibit_charge);
-
- if (port_id >= CONFIG_USB_PORT_POWER_SMART_PORT_COUNT)
- return EC_ERROR_INVAL;
-
- if (mode == USB_CHARGE_MODE_DEFAULT)
- mode = CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE;
-
- switch (mode) {
- case USB_CHARGE_MODE_DISABLED:
- usb_charge_set_enabled(port_id, 0);
- break;
- case USB_CHARGE_MODE_SDP2:
- usb_charge_set_control_mode(port_id, 7);
- usb_charge_set_ilim(port_id, 0);
- usb_charge_set_enabled(port_id, 1);
- break;
- case USB_CHARGE_MODE_CDP:
- usb_charge_set_control_mode(port_id, 7);
- usb_charge_set_ilim(port_id, 1);
- usb_charge_set_enabled(port_id, 1);
- break;
-#ifndef CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY
- case USB_CHARGE_MODE_DCP_SHORT:
- usb_charge_set_control_mode(port_id, 4);
- usb_charge_set_enabled(port_id, 1);
- break;
-#endif /* !defined(CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY) */
- default:
- return EC_ERROR_UNKNOWN;
- }
-
- charge_mode[port_id].mode = mode;
- charge_mode[port_id].inhibit_charging_in_suspend = inhibit_charge;
-
- return EC_SUCCESS;
-}
-
-/*****************************************************************************/
-/* Console commands */
-
-static int command_set_mode(int argc, char **argv)
-{
- int port_id = -1;
- int mode = -1, inhibit_charge = 0;
- char *e;
- int i;
-
- if (argc == 1) {
- for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++)
- ccprintf("Port %d: %d,%d\n", i, charge_mode[i].mode,
- charge_mode[i].inhibit_charging_in_suspend);
- return EC_SUCCESS;
- }
-
- if (argc != 3 && argc != 4)
- return EC_ERROR_PARAM_COUNT;
-
- port_id = strtoi(argv[1], &e, 0);
- if (*e || port_id < 0 ||
- port_id >= CONFIG_USB_PORT_POWER_SMART_PORT_COUNT)
- return EC_ERROR_PARAM1;
-
- mode = strtoi(argv[2], &e, 0);
- if (*e || mode < 0 || mode >= USB_CHARGE_MODE_COUNT)
- return EC_ERROR_PARAM2;
-
- if (argc == 4) {
- inhibit_charge = strtoi(argv[3], &e, 0);
- if (*e || (inhibit_charge != 0 && inhibit_charge != 1))
- return EC_ERROR_PARAM3;
- }
-
- return usb_charge_set_mode(port_id, mode, inhibit_charge);
-}
-DECLARE_CONSOLE_COMMAND(usbchargemode, command_set_mode,
- "[<port> <0 | 1 | 2 | 3> [<0 | 1>]]",
- "Set USB charge mode");
-
-/*****************************************************************************/
-/* Host commands */
-
-static enum ec_status
-usb_charge_command_set_mode(struct host_cmd_handler_args *args)
-{
- const struct ec_params_usb_charge_set_mode *p = args->params;
-
- if (usb_charge_set_mode(p->usb_port_id, p->mode,
- p->inhibit_charge) != EC_SUCCESS)
- return EC_RES_ERROR;
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_USB_CHARGE_SET_MODE,
- usb_charge_command_set_mode,
- EC_VER_MASK(0));
-
-/*****************************************************************************/
-/* Hooks */
-
-static void usb_charge_preserve_state(void)
-{
- system_add_jump_tag(USB_SYSJUMP_TAG, USB_HOOK_VERSION,
- sizeof(charge_mode), charge_mode);
-}
-DECLARE_HOOK(HOOK_SYSJUMP, usb_charge_preserve_state, HOOK_PRIO_DEFAULT);
-
-static void usb_charge_init(void)
-{
- const struct charge_mode_t *prev;
- int version, size, i;
-
- prev = (const struct charge_mode_t *)system_get_jump_tag(USB_SYSJUMP_TAG,
- &version, &size);
-
- if (!prev || version != USB_HOOK_VERSION ||
- size != sizeof(charge_mode)) {
- usb_charge_all_ports_ctrl(USB_CHARGE_MODE_DISABLED);
- return;
- }
-
- for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++)
- usb_charge_set_mode(i, prev[i].mode,
- prev[i].inhibit_charging_in_suspend);
-}
-DECLARE_HOOK(HOOK_INIT, usb_charge_init, HOOK_PRIO_DEFAULT);
-
-static void usb_charge_resume(void)
-{
- int i;
-
- /* Turn on USB ports on as we go into S0 from S3 or S5. */
- for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++)
- usb_charge_set_mode(i,
- CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE,
- charge_mode[i].inhibit_charging_in_suspend);
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, usb_charge_resume, HOOK_PRIO_DEFAULT);
-
-static void usb_charge_suspend(void)
-{
- int i;
-
- /*
- * Inhibit charging during suspend if the inhibit_charging_in_suspend
- * is set to 1.
- */
- for (i = 0; i < CONFIG_USB_PORT_POWER_SMART_PORT_COUNT; i++)
- if (charge_mode[i].inhibit_charging_in_suspend)
- usb_charge_set_enabled(i, 0 /* disabled */);
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, usb_charge_suspend, HOOK_PRIO_DEFAULT);
-
-static void usb_charge_shutdown(void)
-{
- /* Turn on USB ports off as we go back to S5. */
- usb_charge_all_ports_ctrl(USB_CHARGE_MODE_DISABLED);
-}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, usb_charge_shutdown, HOOK_PRIO_DEFAULT);
diff --git a/common/usb_update.c b/common/usb_update.c
deleted file mode 100644
index 3b307ede9a..0000000000
--- a/common/usb_update.c
+++ /dev/null
@@ -1,594 +0,0 @@
-/* Copyright 2016 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.
- */
-
-#include "byteorder.h"
-#include "common.h"
-#include "console.h"
-#include "consumer.h"
-#include "curve25519.h"
-#include "flash.h"
-#include "queue_policies.h"
-#include "host_command.h"
-#include "rollback.h"
-#include "rwsig.h"
-#include "sha256.h"
-#include "system.h"
-#include "uart.h"
-#include "update_fw.h"
-#include "usb-stream.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_USB, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args)
-
-/*
- * This file is an adaptation layer between the USB interface and the firmware
- * update engine. The engine expects to receive long blocks of data, 1K or so
- * in size, prepended by the offset where the data needs to be programmed into
- * the flash and a 4 byte integrity check value.
- *
- * The USB transfer, on the other hand, operates on much shorter chunks of
- * data, typically 64 bytes in this case. This module reassembles firmware
- * programming blocks from the USB chunks, and invokes the programmer passing
- * it the full block.
- *
- * The programmer reports results by putting the return value into the same
- * buffer where the block was passed in. This wrapper retrieves the
- * programmer's return value, and sends it back to the host. The return value
- * is usually one byte in size, the only exception is the connection
- * establishment phase where the return value is 16 bytes in size.
- *
- * In the end of the successful image transfer and programming, the host sends
- * the reset command, and the device reboots itself.
- */
-
-struct consumer const update_consumer;
-struct usb_stream_config const usb_update;
-
-static struct queue const update_to_usb = QUEUE_DIRECT(64, uint8_t,
- null_producer,
- usb_update.consumer);
-static struct queue const usb_to_update = QUEUE_DIRECT(64, uint8_t,
- usb_update.producer,
- update_consumer);
-
-USB_STREAM_CONFIG_FULL(usb_update,
- USB_IFACE_UPDATE,
- USB_CLASS_VENDOR_SPEC,
- USB_SUBCLASS_GOOGLE_UPDATE,
- USB_PROTOCOL_GOOGLE_UPDATE,
- USB_STR_UPDATE_NAME,
- USB_EP_UPDATE,
- USB_MAX_PACKET_SIZE,
- USB_MAX_PACKET_SIZE,
- usb_to_update,
- update_to_usb)
-
-
-/* The receiver can be in one of the states below. */
-enum rx_state {
- rx_idle, /* Nothing happened yet. */
- rx_inside_block, /* Assembling a block to pass to the programmer. */
- rx_outside_block, /* Waiting for the next block to start or for the
- reset command. */
-};
-
-enum rx_state rx_state_ = rx_idle;
-static uint8_t block_buffer[sizeof(struct update_command) +
- CONFIG_UPDATE_PDU_SIZE];
-static uint32_t block_size;
-static uint32_t block_index;
-
-#ifdef CONFIG_USB_PAIRING
-#define KEY_CONTEXT "device-identity"
-
-static int pair_challenge(struct pair_challenge *challenge)
-{
- uint8_t response;
-
- /* Scratchpad for device secret and x25519 public/shared key. */
- uint8_t tmp[32];
- BUILD_ASSERT(sizeof(tmp) >= X25519_PUBLIC_VALUE_LEN);
- BUILD_ASSERT(sizeof(tmp) >= X25519_PRIVATE_KEY_LEN);
- BUILD_ASSERT(sizeof(tmp) >= CONFIG_ROLLBACK_SECRET_SIZE);
-
- /* Scratchpad for device_private and authenticator. */
- uint8_t tmp2[32];
- BUILD_ASSERT(sizeof(tmp2) >= X25519_PRIVATE_KEY_LEN);
- BUILD_ASSERT(sizeof(tmp2) >= SHA256_DIGEST_SIZE);
-
- /* tmp = device_secret */
- if (rollback_get_secret(tmp) != EC_SUCCESS) {
- response = EC_RES_UNAVAILABLE;
- QUEUE_ADD_UNITS(&update_to_usb, &response, sizeof(response));
- return 1;
- }
-
- /*
- * Nothing can fail from now on, let's push data to the queue as soon as
- * possible to save some temporary variables.
- */
- response = EC_RES_SUCCESS;
- QUEUE_ADD_UNITS(&update_to_usb, &response, sizeof(response));
-
- /*
- * tmp2 = device_private
- * = HMAC_SHA256(device_secret, "device-identity")
- */
- hmac_SHA256(tmp2, tmp, CONFIG_ROLLBACK_SECRET_SIZE,
- KEY_CONTEXT, sizeof(KEY_CONTEXT) - 1);
-
- /* tmp = device_public = x25519(device_private, x25519_base_point) */
- X25519_public_from_private(tmp, tmp2);
- QUEUE_ADD_UNITS(&update_to_usb, tmp, sizeof(tmp));
-
- /* tmp = shared_secret = x25519(device_private, host_public) */
- X25519(tmp, tmp2, challenge->host_public);
-
- /* tmp2 = authenticator = HMAC_SHA256(shared_secret, nonce) */
- hmac_SHA256(tmp2, tmp, sizeof(tmp),
- challenge->nonce, sizeof(challenge->nonce));
- QUEUE_ADD_UNITS(&update_to_usb, tmp2,
- member_size(struct pair_challenge_response, authenticator));
- return 1;
-}
-#endif
-
-/*
- * Fetches a transfer start frame from the queue. This can be either an update
- * start frame (block_size = 0, all of cmd = 0), or the beginning of a frame
- * (block_size > 0, valid block_base in cmd).
- */
-static int fetch_transfer_start(struct consumer const *consumer, size_t count,
- struct update_frame_header *pupfr)
-{
- int i;
-
- /*
- * Let's just make sure we drain the queue no matter what the contents
- * are. This way they won't be in the way during next callback, even
- * if these contents are not what's expected.
- *
- * Note: If count > sizeof(*pupfr), pupfr will be corrupted. This is
- * ok as we will immediately fail after this.
- */
- i = count;
- while (i > 0) {
- QUEUE_REMOVE_UNITS(consumer->queue, pupfr,
- MIN(i, sizeof(*pupfr)));
- i -= sizeof(*pupfr);
- }
-
- if (count != sizeof(struct update_frame_header)) {
- CPRINTS("FW update: wrong first block, size %d", count);
- return 0;
- }
-
- return 1;
-}
-
-static int try_vendor_command(struct consumer const *consumer, size_t count)
-{
- char buffer[USB_MAX_PACKET_SIZE];
- struct update_frame_header *cmd_buffer = (void *)buffer;
- int rv = 0;
-
- /* Validate count (too short, or too long). */
- if (count < sizeof(*cmd_buffer) || count > sizeof(buffer))
- return 0;
-
- /*
- * Let's copy off the queue the update frame header, to see if this
- * is a channeled vendor command.
- */
- queue_peek_units(consumer->queue, cmd_buffer, 0, sizeof(*cmd_buffer));
- if (be32toh(cmd_buffer->cmd.block_base) != UPDATE_EXTRA_CMD)
- return 0;
-
- if (be32toh(cmd_buffer->block_size) != count) {
- CPRINTS("%s: problem: block size and count mismatch (%d != %d)",
- __func__, be32toh(cmd_buffer->block_size), count);
- return 0;
- }
-
- /* Get the entire command, don't remove it from the queue just yet. */
- queue_peek_units(consumer->queue, cmd_buffer, 0, count);
-
- /* Looks like this is a vendor command, let's verify it. */
- if (update_pdu_valid(&cmd_buffer->cmd,
- count - offsetof(struct update_frame_header, cmd))) {
- enum update_extra_command subcommand;
- uint8_t response;
- size_t response_size = sizeof(response);
- int __attribute__((unused)) header_size;
- int __attribute__((unused)) data_count;
-
- /* looks good, let's process it. */
- rv = 1;
-
- /* Now remove it from the queue. */
- queue_advance_head(consumer->queue, count);
-
- subcommand = be16toh(*((uint16_t *)(cmd_buffer + 1)));
-
- /*
- * header size: update frame header + 2 bytes for subcommand
- * data_count: Some commands take in extra data as parameter
- */
- header_size = sizeof(*cmd_buffer) + sizeof(uint16_t);
- data_count = count - header_size;
-
- switch (subcommand) {
- case UPDATE_EXTRA_CMD_IMMEDIATE_RESET:
- CPRINTS("Rebooting!");
- CPRINTF("\n\n");
- cflush();
- system_reset(SYSTEM_RESET_MANUALLY_TRIGGERED);
- /* Unreachable, unless something bad happens. */
- response = EC_RES_ERROR;
- break;
- case UPDATE_EXTRA_CMD_JUMP_TO_RW:
-#ifdef CONFIG_RWSIG
- /*
- * Tell rwsig task to jump to RW. This does nothing if
- * verification failed, and will only jump later on if
- * verification is still in progress.
- */
- rwsig_continue();
-
- switch (rwsig_get_status()) {
- case RWSIG_VALID:
- response = EC_RES_SUCCESS;
- break;
- case RWSIG_INVALID:
- response = EC_RES_INVALID_CHECKSUM;
- break;
- case RWSIG_IN_PROGRESS:
- response = EC_RES_IN_PROGRESS;
- break;
- default:
- response = EC_RES_ERROR;
- }
-#else
- system_run_image_copy(EC_IMAGE_RW);
-#endif
- break;
-#ifdef CONFIG_RWSIG
- case UPDATE_EXTRA_CMD_STAY_IN_RO:
- rwsig_abort();
- response = EC_RES_SUCCESS;
- break;
-#endif
- case UPDATE_EXTRA_CMD_UNLOCK_RW:
- crec_flash_set_protect(EC_FLASH_PROTECT_RW_AT_BOOT, 0);
- response = EC_RES_SUCCESS;
- break;
-#ifdef CONFIG_ROLLBACK
- case UPDATE_EXTRA_CMD_UNLOCK_ROLLBACK:
- crec_flash_set_protect(EC_FLASH_PROTECT_ROLLBACK_AT_BOOT
- , 0);
- response = EC_RES_SUCCESS;
- break;
-#ifdef CONFIG_ROLLBACK_SECRET_SIZE
-#ifdef CONFIG_ROLLBACK_UPDATE
- case UPDATE_EXTRA_CMD_INJECT_ENTROPY: {
- if (data_count < CONFIG_ROLLBACK_SECRET_SIZE) {
- CPRINTS("Entropy too short");
- response = EC_RES_INVALID_PARAM;
- break;
- }
-
- CPRINTS("Adding %db of entropy", data_count);
- /* Add the entropy to secret. */
- rollback_add_entropy(buffer + header_size, data_count);
- break;
- }
-#endif /* CONFIG_ROLLBACK_UPDATE */
-#ifdef CONFIG_USB_PAIRING
- case UPDATE_EXTRA_CMD_PAIR_CHALLENGE: {
- if (data_count < sizeof(struct pair_challenge)) {
- CPRINTS("Challenge data too short");
- response = EC_RES_INVALID_PARAM;
- break;
- }
-
- /* pair_challenge takes care of answering */
- return pair_challenge((struct pair_challenge *)
- (buffer + header_size));
- }
-#endif
-#endif /* CONFIG_ROLLBACK_SECRET_SIZE */
-#endif /* CONFIG_ROLLBACK */
-#ifdef CONFIG_TOUCHPAD
- case UPDATE_EXTRA_CMD_TOUCHPAD_INFO: {
- struct touchpad_info tp = { 0 };
-
- if (data_count != 0) {
- response = EC_RES_INVALID_PARAM;
- break;
- }
-
- response_size = touchpad_get_info(&tp);
- if (response_size < 1) {
- response = EC_RES_ERROR;
- break;
- }
-
-#ifdef CONFIG_TOUCHPAD_VIRTUAL_OFF
- tp.fw_address = CONFIG_TOUCHPAD_VIRTUAL_OFF;
- tp.fw_size = CONFIG_TOUCHPAD_VIRTUAL_SIZE;
-
-#ifdef CONFIG_TOUCHPAD_HASH_FW
- memcpy(tp.allowed_fw_hash, touchpad_fw_full_hash,
- sizeof(tp.allowed_fw_hash));
-#endif
-#endif /* CONFIG_TOUCHPAD_VIRTUAL_OFF */
- QUEUE_ADD_UNITS(&update_to_usb,
- &tp, response_size);
- return 1;
- }
- case UPDATE_EXTRA_CMD_TOUCHPAD_DEBUG: {
- uint8_t *data = NULL;
- unsigned int write_count = 0;
-
- /*
- * Let the touchpad driver decide what it wants to do
- * with the payload data, and put the response in data.
- */
- response = touchpad_debug(buffer + header_size,
- data_count, &data, &write_count);
-
- /*
- * On error, or if there is no data to write back, just
- * write back response.
- */
- if (response != EC_RES_SUCCESS || write_count == 0)
- break;
-
- /* Check that we can write all the data to the queue. */
- if (write_count > queue_space(&update_to_usb))
- return EC_RES_BUSY;
-
- QUEUE_ADD_UNITS(&update_to_usb, data, write_count);
- return 1;
- }
-#endif
-#ifdef CONFIG_USB_CONSOLE_READ
- /*
- * TODO(b/112877237): move this to a new interface, so we can
- * support reading log and other commands at the same time?
- */
- case UPDATE_EXTRA_CMD_CONSOLE_READ_INIT:
- response = uart_console_read_buffer_init();
- break;
- case UPDATE_EXTRA_CMD_CONSOLE_READ_NEXT: {
- uint8_t *data = buffer + header_size;
- uint8_t output[64];
- uint16_t write_count = 0;
-
- if (data_count != 1) {
- response = EC_RES_INVALID_PARAM;
- break;
- }
-
- response = uart_console_read_buffer(
- data[0],
- (char *)output,
- MIN(sizeof(output),
- queue_space(&update_to_usb)),
- &write_count);
- if (response != EC_RES_SUCCESS || write_count == 0)
- break;
-
- QUEUE_ADD_UNITS(&update_to_usb, output, write_count);
- return 1;
- }
-#endif
- default:
- response = EC_RES_INVALID_COMMAND;
- }
-
- QUEUE_ADD_UNITS(&update_to_usb, &response, response_size);
- }
-
- return rv;
-}
-
-/*
- * When was last time a USB callback was called, in microseconds, free running
- * timer.
- */
-static uint64_t prev_activity_timestamp;
-
-/*
- * A flag indicating that at least one valid PDU containing flash update block
- * has been received in the current transfer session.
- */
-static uint8_t data_was_transferred;
-
-/* Reply with an error to remote side, reset state. */
-static void send_error_reset(uint8_t resp_value)
-{
- QUEUE_ADD_UNITS(&update_to_usb, &resp_value, 1);
- rx_state_ = rx_idle;
- data_was_transferred = 0;
-}
-
-/* Called to deal with data from the host */
-static void update_out_handler(struct consumer const *consumer, size_t count)
-{
- struct update_frame_header upfr;
- size_t resp_size;
- uint8_t resp_value;
- uint64_t delta_time;
-
- /* How much time since the previous USB callback? */
- delta_time = get_time().val - prev_activity_timestamp;
- prev_activity_timestamp += delta_time;
-
- /* If timeout exceeds 5 seconds - let's start over. */
- if ((delta_time > 5000000) && (rx_state_ != rx_idle)) {
- rx_state_ = rx_idle;
- CPRINTS("FW update: recovering after timeout");
- }
-
- if (rx_state_ == rx_idle) {
- /*
- * The payload must be an update initiating PDU.
- *
- * The size of the response returned in the same buffer will
- * exceed the received frame size; Let's make sure there is
- * enough room for the response in the buffer.
- */
- union {
- struct update_frame_header upfr;
- struct {
- uint32_t unused;
- struct first_response_pdu startup_resp;
- };
- } u;
-
- /* Check is this is a channeled TPM extension command. */
- if (try_vendor_command(consumer, count))
- return;
-
- /*
- * An update start PDU is a command without any payload, with
- * digest = 0, and base = 0.
- */
- if (!fetch_transfer_start(consumer, count, &u.upfr) ||
- be32toh(u.upfr.block_size) !=
- sizeof(struct update_frame_header) ||
- u.upfr.cmd.block_digest != 0 ||
- u.upfr.cmd.block_base != 0) {
- /*
- * Something is wrong, this payload is not a valid
- * update start PDU. Let'w indicate this by returning
- * a single byte error code.
- */
- CPRINTS("FW update: invalid start.");
- send_error_reset(UPDATE_GEN_ERROR);
- return;
- }
-
- CPRINTS("FW update: starting...");
- fw_update_command_handler(&u.upfr.cmd, count -
- offsetof(struct update_frame_header,
- cmd),
- &resp_size);
-
- if (!u.startup_resp.return_value) {
- rx_state_ = rx_outside_block; /* We're in business. */
- data_was_transferred = 0; /* No data received yet. */
- }
-
- /* Let the host know what updater had to say. */
- QUEUE_ADD_UNITS(&update_to_usb, &u.startup_resp, resp_size);
- return;
- }
-
- if (rx_state_ == rx_outside_block) {
- /*
- * Expecting to receive the beginning of the block or the
- * reset command if all data blocks have been processed.
- */
- if (count == 4) {
- uint32_t command;
-
- QUEUE_REMOVE_UNITS(consumer->queue, &command,
- sizeof(command));
- command = be32toh(command);
- if (command == UPDATE_DONE) {
- CPRINTS("FW update: done");
-
- if (data_was_transferred) {
- fw_update_complete();
- data_was_transferred = 0;
- }
-
- resp_value = 0;
- QUEUE_ADD_UNITS(&update_to_usb,
- &resp_value, 1);
- rx_state_ = rx_idle;
- return;
- }
- }
-
- /*
- * At this point we expect a block start message. It is
- * sizeof(upfr) bytes in size.
- */
- if (!fetch_transfer_start(consumer, count, &upfr)) {
- CPRINTS("Invalid block start.");
- send_error_reset(UPDATE_GEN_ERROR);
- return;
- }
-
- /* Let's allocate a large enough buffer. */
- block_size = be32toh(upfr.block_size) -
- offsetof(struct update_frame_header, cmd);
-
- /*
- * Only update start PDU is allowed to have a size 0 payload.
- */
- if (block_size <= sizeof(struct update_command) ||
- block_size > sizeof(block_buffer)) {
- CPRINTS("Invalid block size (%d).", block_size);
- send_error_reset(UPDATE_GEN_ERROR);
- return;
- }
-
- /*
- * Copy the rest of the message into the block buffer to pass
- * to the updater.
- */
- block_index = sizeof(upfr) -
- offsetof(struct update_frame_header, cmd);
- memcpy(block_buffer, &upfr.cmd, block_index);
- block_size -= block_index;
- rx_state_ = rx_inside_block;
- return;
- }
-
- /* Must be inside block. */
- QUEUE_REMOVE_UNITS(consumer->queue, block_buffer + block_index, count);
- block_index += count;
- block_size -= count;
-
- if (block_size) {
- if (count <= sizeof(upfr)) {
- /*
- * A block header size instead of chunk size message
- * has been received, let's abort the transfer.
- */
- CPRINTS("Unexpected header");
- send_error_reset(UPDATE_GEN_ERROR);
- return;
- }
- return; /* More to come. */
- }
-
- /*
- * Ok, the entire block has been received and reassembled, pass it to
- * the updater for verification and programming.
- */
- fw_update_command_handler(block_buffer, block_index, &resp_size);
-
- /*
- * There was at least an attempt to program the flash, set the
- * flag.
- */
- data_was_transferred = 1;
- resp_value = block_buffer[0];
- QUEUE_ADD_UNITS(&update_to_usb, &resp_value, sizeof(resp_value));
- rx_state_ = rx_outside_block;
-}
-
-struct consumer const update_consumer = {
- .queue = &usb_to_update,
- .ops = &((struct consumer_ops const) {
- .written = update_out_handler,
- }),
-};
diff --git a/common/usbc/build.mk b/common/usbc/build.mk
deleted file mode 100644
index 48ab5351b8..0000000000
--- a/common/usbc/build.mk
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright 2019 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.
-
-# Build for USB Type-C and Power Delivery
-
-# Note that this variable includes the trailing "/"
-_usbc_dir:=$(dir $(lastword $(MAKEFILE_LIST)))
-
-ifneq ($(CONFIG_USB_PD_TCPMV2),)
-all-obj-$(CONFIG_USB_PD_TCPMV2)+=$(_usbc_dir)usb_pd_timer.o
-all-obj-$(CONFIG_USB_PD_TCPMV2)+=$(_usbc_dir)usb_sm.o
-all-obj-$(CONFIG_USB_PD_TCPMV2)+=$(_usbc_dir)usbc_task.o
-
-# Type-C state machines
-ifneq ($(CONFIG_USB_TYPEC_SM),)
-all-obj-$(CONFIG_USB_VPD)+=$(_usbc_dir)usb_tc_vpd_sm.o
-all-obj-$(CONFIG_USB_CTVPD)+=$(_usbc_dir)usb_tc_ctvpd_sm.o
-all-obj-$(CONFIG_USB_DRP_ACC_TRYSRC)+=$(_usbc_dir)usb_tc_drp_acc_trysrc_sm.o
-endif # CONFIG_USB_TYPEC_SM
-
-# Protocol state machine
-ifneq ($(CONFIG_USB_PRL_SM),)
-all-obj-$(CONFIG_USB_PD_TCPMV2)+=$(_usbc_dir)usb_prl_sm.o
-endif # CONFIG_USB_PRL_SM
-
-# Policy Engine state machines
-ifneq ($(CONFIG_USB_PE_SM),)
-all-obj-$(CONFIG_USB_VPD)+=$(_usbc_dir)usb_pe_ctvpd_sm.o
-all-obj-$(CONFIG_USB_CTVPD)+=$(_usbc_dir)usb_pe_ctvpd_sm.o
-all-obj-$(CONFIG_USB_DRP_ACC_TRYSRC)+=$(_usbc_dir)usbc_pd_policy.o
-all-obj-$(CONFIG_USB_DRP_ACC_TRYSRC)+=$(_usbc_dir)usb_pe_drp_sm.o
-all-obj-$(CONFIG_USB_DRP_ACC_TRYSRC)+=$(_usbc_dir)usb_pd_dpm.o
-all-obj-$(CONFIG_USB_DRP_ACC_TRYSRC)+=$(_usbc_dir)dp_alt_mode.o
-all-obj-$(CONFIG_USB_PD_TBT_COMPAT_MODE)+=$(_usbc_dir)tbt_alt_mode.o
-all-obj-$(CONFIG_USB_PD_USB4)+=$(_usbc_dir)usb_mode.o
-all-obj-$(CONFIG_CMD_PD)+=$(_usbc_dir)usb_pd_console.o
-all-obj-$(CONFIG_USB_PD_HOST_CMD)+=$(_usbc_dir)usb_pd_host.o
-endif # CONFIG_USB_PE_SM
-
-# Retimer firmware update
-all-obj-$(CONFIG_USBC_RETIMER_FW_UPDATE)+=$(_usbc_dir)usb_retimer_fw_update.o
-
-# ALT-DP mode for UFP ports
-all-obj-$(CONFIG_USB_PD_ALT_MODE_UFP_DP)+=$(_usbc_dir)usb_pd_dp_ufp.o
-endif # CONFIG_USB_PD_TCPMV2
-
-# For testing
-all-obj-$(CONFIG_TEST_USB_PE_SM)+=$(_usbc_dir)usbc_pd_policy.o
-all-obj-$(CONFIG_TEST_USB_PE_SM)+=$(_usbc_dir)usb_pe_drp_sm.o
-all-obj-$(CONFIG_TEST_SM)+=$(_usbc_dir)usb_sm.o
diff --git a/common/usbc/dp_alt_mode.c b/common/usbc/dp_alt_mode.c
deleted file mode 100644
index 9a3493c6e1..0000000000
--- a/common/usbc/dp_alt_mode.c
+++ /dev/null
@@ -1,292 +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.
- */
-
-/*
- * DisplayPort alternate mode support
- * Refer to VESA DisplayPort Alt Mode on USB Type-C Standard, version 2.0,
- * section 5.2
- */
-
-#include <stdbool.h>
-#include <stdint.h>
-#include "assert.h"
-#include "usb_common.h"
-#include "usb_dp_alt_mode.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#else
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif
-
-/* The state of the DP negotiation */
-enum dp_states {
- DP_START = 0,
- DP_ENTER_ACKED,
- DP_ENTER_NAKED,
- DP_STATUS_ACKED,
- DP_ACTIVE,
- DP_ENTER_RETRY,
- DP_INACTIVE,
- DP_STATE_COUNT
-};
-static enum dp_states dp_state[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/*
- * Map of states to expected VDM commands in responses.
- * Default of 0 indicates no command expected.
- */
-static const uint8_t state_vdm_cmd[DP_STATE_COUNT] = {
- [DP_START] = CMD_ENTER_MODE,
- [DP_ENTER_ACKED] = CMD_DP_STATUS,
- [DP_STATUS_ACKED] = CMD_DP_CONFIG,
- [DP_ACTIVE] = CMD_EXIT_MODE,
- [DP_ENTER_NAKED] = CMD_EXIT_MODE,
- [DP_ENTER_RETRY] = CMD_ENTER_MODE,
-};
-
-bool dp_is_active(int port)
-{
- return dp_state[port] == DP_ACTIVE;
-}
-
-void dp_init(int port)
-{
- dp_state[port] = DP_START;
-}
-
-bool dp_entry_is_done(int port)
-{
- return dp_state[port] == DP_ACTIVE ||
- dp_state[port] == DP_INACTIVE;
-}
-
-static void dp_entry_failed(int port)
-{
- CPRINTS("C%d: DP alt mode protocol failed!", port);
- dp_state[port] = DP_INACTIVE;
-}
-
-static bool dp_response_valid(int port, enum tcpci_msg_type type,
- char *cmdt, int vdm_cmd)
-{
- enum dp_states st = dp_state[port];
-
- /*
- * Check for an unexpected response.
- * If DP is inactive, ignore the command.
- */
- if (type != TCPCI_MSG_SOP ||
- (st != DP_INACTIVE && state_vdm_cmd[st] != vdm_cmd)) {
- CPRINTS("C%d: Received unexpected DP VDM %s (cmd %d) from"
- " %s in state %d", port, cmdt, vdm_cmd,
- type == TCPCI_MSG_SOP ? "port partner" : "cable plug",
- st);
- dp_entry_failed(port);
- return false;
- }
- return true;
-}
-
-static void dp_exit_to_usb_mode(int port)
-{
- int opos = pd_alt_mode(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT);
-
- pd_dfp_exit_mode(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT, opos);
- set_usb_mux_with_current_data_role(port);
-
- CPRINTS("C%d: Exited DP mode", port);
- /*
- * If the EC exits an alt mode autonomously, don't try to enter it again. If
- * the AP commands the EC to exit DP mode, it might command the EC to enter
- * again later, so leave the state machine ready for that possibility.
- */
- dp_state[port] = IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY)
- ? DP_START : DP_INACTIVE;
-}
-
-void dp_vdm_acked(int port, enum tcpci_msg_type type, int vdo_count,
- uint32_t *vdm)
-{
- const struct svdm_amode_data *modep =
- pd_get_amode_data(port, type, USB_SID_DISPLAYPORT);
- const uint8_t vdm_cmd = PD_VDO_CMD(vdm[0]);
-
- if (!dp_response_valid(port, type, "ACK", vdm_cmd))
- return;
-
- /* TODO(b/155890173): Validate VDO count for specific commands */
-
- switch (dp_state[port]) {
- case DP_START:
- case DP_ENTER_RETRY:
- dp_state[port] = DP_ENTER_ACKED;
- /* Inform PE layer that alt mode is now active */
- pd_set_dfp_enter_mode_flag(port, true);
- break;
- case DP_ENTER_ACKED:
- /* DP status response & UFP's DP attention have same payload. */
- dfp_consume_attention(port, vdm);
- dp_state[port] = DP_STATUS_ACKED;
- break;
- case DP_STATUS_ACKED:
- if (modep && modep->opos && modep->fx->post_config)
- modep->fx->post_config(port);
- dp_state[port] = DP_ACTIVE;
- CPRINTS("C%d: Entered DP mode", port);
- break;
- case DP_ACTIVE:
- /*
- * Request to exit mode successful, so put the module in an
- * inactive state.
- */
- dp_exit_to_usb_mode(port);
- break;
- case DP_ENTER_NAKED:
- /*
- * The request to exit the mode was successful,
- * so try to enter the mode again.
- */
- dp_state[port] = DP_ENTER_RETRY;
- break;
- case DP_INACTIVE:
- /*
- * This can occur if the mode is shutdown because
- * the CPU is being turned off, and an exit mode
- * command has been sent.
- */
- break;
- default:
- /* Invalid or unexpected negotiation state */
- CPRINTF("%s called with invalid state %d\n",
- __func__, dp_state[port]);
- dp_entry_failed(port);
- break;
- }
-}
-
-void dp_vdm_naked(int port, enum tcpci_msg_type type, uint8_t vdm_cmd)
-{
- if (!dp_response_valid(port, type, "NAK", vdm_cmd))
- return;
-
- switch (dp_state[port]) {
- case DP_START:
- /*
- * If a request to enter DP mode is NAK'ed, this likely
- * means the partner is already in DP alt mode, so
- * request to exit the mode first before retrying
- * the enter command. This can happen if the EC
- * is restarted (e.g to go into recovery mode) while
- * DP alt mode is active.
- */
- dp_state[port] = DP_ENTER_NAKED;
- break;
- case DP_ENTER_RETRY:
- /*
- * Another NAK on the second attempt to enter DP mode.
- * Give up.
- */
- dp_entry_failed(port);
- break;
- case DP_ACTIVE:
- /* Treat an Exit Mode NAK the same as an Exit Mode ACK. */
- dp_exit_to_usb_mode(port);
- break;
- default:
- CPRINTS("C%d: NAK for cmd %d in state %d", port,
- vdm_cmd, dp_state[port]);
- dp_entry_failed(port);
- break;
- }
-}
-
-int dp_setup_next_vdm(int port, int vdo_count, uint32_t *vdm)
-{
- const struct svdm_amode_data *modep = pd_get_amode_data(port,
- TCPCI_MSG_SOP, USB_SID_DISPLAYPORT);
- int vdo_count_ret;
-
- if (vdo_count < VDO_MAX_SIZE)
- return -1;
-
- switch (dp_state[port]) {
- case DP_START:
- case DP_ENTER_RETRY:
- /* Enter the first supported mode for DisplayPort. */
- vdm[0] = pd_dfp_enter_mode(port, TCPCI_MSG_SOP,
- USB_SID_DISPLAYPORT, 0);
- if (vdm[0] == 0)
- return -1;
- /* CMDT_INIT is 0, so this is a no-op */
- vdm[0] |= VDO_CMDT(CMDT_INIT);
- vdm[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP));
- vdo_count_ret = 1;
- if (dp_state[port] == DP_START)
- CPRINTS("C%d: Attempting to enter DP mode", port);
- break;
- case DP_ENTER_ACKED:
- if (!(modep && modep->opos))
- return -1;
-
- vdo_count_ret = modep->fx->status(port, vdm);
- if (vdo_count_ret == 0)
- return -1;
- vdm[0] |= PD_VDO_OPOS(modep->opos);
- vdm[0] |= VDO_CMDT(CMDT_INIT);
- vdm[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP));
- break;
- case DP_STATUS_ACKED:
- if (!(modep && modep->opos))
- return -1;
-
- vdo_count_ret = modep->fx->config(port, vdm);
- if (vdo_count_ret == 0)
- return -1;
- vdm[0] |= VDO_CMDT(CMDT_INIT);
- vdm[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP));
- break;
- case DP_ENTER_NAKED:
- case DP_ACTIVE:
- /*
- * Called to exit DP alt mode, either when the mode
- * is active and the system is shutting down, or
- * when an initial request to enter the mode is NAK'ed.
- * This can happen if the EC is restarted (e.g to go
- * into recovery mode) while DP alt mode is active.
- * It would be good to invoke modep->fx->exit but
- * this doesn't set up the VDM, it clears state.
- * TODO(b/159856063): Clean up the API to the fx functions.
- */
- if (!(modep && modep->opos))
- return -1;
-
- usb_mux_set_safe_mode_exit(port);
-
- vdm[0] = VDO(USB_SID_DISPLAYPORT,
- 1, /* structured */
- CMD_EXIT_MODE);
-
- vdm[0] |= VDO_OPOS(modep->opos);
- vdm[0] |= VDO_CMDT(CMDT_INIT);
- vdm[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP));
- vdo_count_ret = 1;
- break;
- case DP_INACTIVE:
- /*
- * DP mode is inactive.
- */
- return -1;
- default:
- CPRINTF("%s called with invalid state %d\n",
- __func__, dp_state[port]);
- return -1;
- }
- return vdo_count_ret;
-}
diff --git a/common/usbc/tbt_alt_mode.c b/common/usbc/tbt_alt_mode.c
deleted file mode 100644
index 73e2796345..0000000000
--- a/common/usbc/tbt_alt_mode.c
+++ /dev/null
@@ -1,579 +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.
- */
-
-/*
- * Thunderbolt alternate mode support
- * Refer to USB Type-C Cable and Connector Specification Release 2.0 Section F
- */
-
-#include "atomic.h"
-#include <stdbool.h>
-#include <stdint.h>
-#include "compile_time_macros.h"
-#include "console.h"
-#include "tcpm/tcpm.h"
-#include "usb_common.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "usb_pd_tbt.h"
-#include "usb_pd_tcpm.h"
-#include "usb_pe_sm.h"
-#include "usb_tbt_alt_mode.h"
-
-/*
- * Enter/Exit TBT mode with active cable
- *
- *
- * TBT_START |------------
- * retry_done = false | |
- * | v |
- * |<------------------| Exit Mode SOP |
- * | retry_done = true | | |
- * v | | ACK/NAK |
- * Enter Mode SOP' | --------|--------- |
- * ACK | NAK | Exit Mode SOP'' |
- * |------|------| | | |
- * | | | | ACK/NAK |
- * v | | --------|--------- |
- * Enter Mode SOP'' | | Exit Mode SOP' |
- * | | | | |
- * ACK | NAK | | | ACK/NAK |
- * |------|------| | | ------------------ |
- * | | | | retry_done == true? |
- * v | | | | |
- * Enter Mode SOP | | | No | |
- * | | | |----------- |
- * ACK | NAK | | |Yes |
- * |-------|------| | | v |
- * | | | | TBT_INACTIVE |
- * v | | | retry_done = false |
- * TBT_ACTIVE | | | |
- * retry_done = true | | | |
- * | | | | |
- * v v v v |
- * -----------------------------------------------------------------|
- */
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#else
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif
-
-/*
- * If a partner sends an Enter Mode NAK, Exit Mode and try again. This has
- * happened when the EC loses state after previously entering an alt mode
- * with a partner. It may be fixed in b/159495742, in which case this
- * logic is unneeded.
- */
-#define TBT_FLAG_RETRY_DONE BIT(0)
-#define TBT_FLAG_EXIT_DONE BIT(1)
-#define TBT_FLAG_CABLE_ENTRY_DONE BIT(2)
-
-static uint8_t tbt_flags[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-#define TBT_SET_FLAG(port, flag) (tbt_flags[port] |= (flag))
-#define TBT_CLR_FLAG(port, flag) (tbt_flags[port] &= (~flag))
-#define TBT_CHK_FLAG(port, flag) (tbt_flags[port] & (flag))
-
-static int tbt_prints(const char *string, int port)
-{
- return CPRINTS("C%d: TBT %s", port, string);
-}
-
-/* The states of Thunderbolt negotiation */
-enum tbt_states {
- TBT_START = 0,
- TBT_ENTER_SOP,
- TBT_ACTIVE,
- TBT_EXIT_SOP,
- TBT_INACTIVE,
- /* Active cable only */
- TBT_ENTER_SOP_PRIME,
- TBT_ENTER_SOP_PRIME_PRIME,
- TBT_EXIT_SOP_PRIME,
- TBT_EXIT_SOP_PRIME_PRIME,
- TBT_STATE_COUNT,
-};
-static enum tbt_states tbt_state[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-static const uint8_t state_vdm_cmd[TBT_STATE_COUNT] = {
- [TBT_ENTER_SOP] = CMD_ENTER_MODE,
- [TBT_ACTIVE] = CMD_EXIT_MODE,
- [TBT_EXIT_SOP] = CMD_EXIT_MODE,
- /* Active cable only */
- [TBT_ENTER_SOP_PRIME] = CMD_ENTER_MODE,
- [TBT_ENTER_SOP_PRIME_PRIME] = CMD_ENTER_MODE,
- [TBT_EXIT_SOP_PRIME] = CMD_EXIT_MODE,
- [TBT_EXIT_SOP_PRIME_PRIME] = CMD_EXIT_MODE,
-};
-
-void tbt_init(int port)
-{
- tbt_state[port] = TBT_START;
- TBT_CLR_FLAG(port, TBT_FLAG_RETRY_DONE);
- TBT_SET_FLAG(port, TBT_FLAG_EXIT_DONE);
- TBT_CLR_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE);
-}
-
-bool tbt_is_active(int port)
-{
- return tbt_state[port] != TBT_INACTIVE &&
- tbt_state[port] != TBT_START;
-}
-
-bool tbt_entry_is_done(int port)
-{
- return tbt_state[port] == TBT_ACTIVE ||
- tbt_state[port] == TBT_INACTIVE;
-}
-
-bool tbt_cable_entry_is_done(int port)
-{
- return TBT_CHK_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE);
-}
-
-static void tbt_exit_done(int port)
-{
- /*
- * If the EC exits an alt mode autonomously, don't try to enter it again. If
- * the AP commands the EC to exit DP mode, it might command the EC to enter
- * again later, so leave the state machine ready for that possibility.
- */
- tbt_state[port] = IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY)
- ? TBT_START : TBT_INACTIVE;
- TBT_CLR_FLAG(port, TBT_FLAG_RETRY_DONE);
- TBT_CLR_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE);
-
- if (!TBT_CHK_FLAG(port, TBT_FLAG_EXIT_DONE)) {
- TBT_SET_FLAG(port, TBT_FLAG_EXIT_DONE);
- tbt_prints("Exited alternate mode", port);
- return;
- }
-
- tbt_prints("alt mode protocol failed!", port);
-}
-
-void tbt_exit_mode_request(int port)
-{
- union tbt_mode_resp_cable cable_mode_resp;
-
- TBT_SET_FLAG(port, TBT_FLAG_RETRY_DONE);
- TBT_CLR_FLAG(port, TBT_FLAG_EXIT_DONE);
- /*
- * If the port has entered USB4 mode with Thunderbolt mode for the
- * cable, on request to exit, only exit Thunderbolt mode for the
- * cable.
- * TODO (b/156749387): Remove once data reset feature is in place.
- */
- if (tbt_state[port] == TBT_ENTER_SOP) {
- cable_mode_resp.raw_value =
- pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME);
-
- /*
- * For Linear re-driver cables, the port enters USB4 mode
- * with Thunderbolt mode for SOP prime. Hence, on request to
- * exit, only exit Thunderbolt mode SOP prime
- */
- tbt_state[port] =
- cable_mode_resp.tbt_active_passive == TBT_CABLE_ACTIVE ?
- TBT_EXIT_SOP_PRIME : TBT_EXIT_SOP_PRIME_PRIME;
- }
-}
-
-static bool tbt_response_valid(int port, enum tcpci_msg_type type,
- char *cmdt, int vdm_cmd)
-{
- enum tbt_states st = tbt_state[port];
- union tbt_mode_resp_cable cable_mode_resp = {
- .raw_value = pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME) };
-
- /*
- * Check for an unexpected response.
- * 1. invalid command
- * 2. invalid Tx type for passive cable
- * If Thunderbolt is inactive, ignore the command.
- */
- if ((st != TBT_INACTIVE && state_vdm_cmd[st] != vdm_cmd) ||
- (get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE &&
- cable_mode_resp.tbt_active_passive == TBT_CABLE_PASSIVE &&
- type != TCPCI_MSG_SOP)) {
- tbt_exit_done(port);
- return false;
- }
- return true;
-}
-
-/* Exit Mode process is complete, but retry Enter Mode process */
-static void tbt_retry_enter_mode(int port)
-{
- tbt_state[port] = TBT_START;
- TBT_SET_FLAG(port, TBT_FLAG_RETRY_DONE);
-}
-
-/* Send Exit Mode to SOP''(if supported), or SOP' */
-static void tbt_active_cable_exit_mode(int port)
-{
- const struct pd_discovery *disc;
-
- disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
-
- if (disc->identity.product_t1.a_rev20.sop_p_p)
- tbt_state[port] = TBT_EXIT_SOP_PRIME_PRIME;
- else
- tbt_state[port] = TBT_EXIT_SOP_PRIME;
-}
-
-bool tbt_cable_entry_required_for_usb4(int port)
-{
- const struct pd_discovery *disc_sop_prime;
- union tbt_mode_resp_cable cable_mode_resp;
-
- /* Request to enter Thunderbolt mode for the cable prior to entering
- * USB4 mode if -
- * 1. Thunderbolt Mode SOP' VDO active/passive bit (B25) is
- * TBT_CABLE_ACTIVE or
- * 2. It's an active cable with VDM version < 2.0 or
- * VDO version < 1.3
- */
- if (tbt_cable_entry_is_done(port))
- return false;
-
- cable_mode_resp.raw_value =
- pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME);
-
- if (cable_mode_resp.tbt_active_passive == TBT_CABLE_ACTIVE)
- return true;
-
- if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) {
- disc_sop_prime = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
- if (pd_get_vdo_ver(port, TCPCI_MSG_SOP_PRIME) < VDM_VER20 ||
- disc_sop_prime->identity.product_t1.a_rev30.vdo_ver <
- VDO_VERSION_1_3)
- return true;
- }
- return false;
-}
-
-void intel_vdm_acked(int port, enum tcpci_msg_type type, int vdo_count,
- uint32_t *vdm)
-{
- const struct pd_discovery *disc;
- const uint8_t vdm_cmd = PD_VDO_CMD(vdm[0]);
- int opos_sop, opos_sop_prime;
- union tbt_mode_resp_cable cable_mode_resp;
-
- if (!tbt_response_valid(port, type, "ACK", vdm_cmd))
- return;
-
- disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
-
- switch (tbt_state[port]) {
- case TBT_ENTER_SOP_PRIME:
- tbt_prints("enter mode SOP'", port);
- cable_mode_resp.raw_value =
- pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME);
- /* For LRD cables, Enter mode SOP' -> Enter mode SOP */
- if (disc->identity.product_t1.a_rev20.sop_p_p &&
- cable_mode_resp.tbt_active_passive != TBT_CABLE_ACTIVE) {
- tbt_state[port] = TBT_ENTER_SOP_PRIME_PRIME;
- } else {
- TBT_SET_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE);
- tbt_state[port] = TBT_ENTER_SOP;
- }
- break;
- case TBT_ENTER_SOP_PRIME_PRIME:
- tbt_prints("enter mode SOP''", port);
- TBT_SET_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE);
- tbt_state[port] = TBT_ENTER_SOP;
- break;
- case TBT_ENTER_SOP:
- set_tbt_compat_mode_ready(port);
- tbt_state[port] = TBT_ACTIVE;
- tbt_prints("enter mode SOP", port);
- TBT_SET_FLAG(port, TBT_FLAG_RETRY_DONE);
- /* Indicate to PE layer that alt mode is active */
- pd_set_dfp_enter_mode_flag(port, true);
- break;
- case TBT_ACTIVE:
- tbt_prints("exit mode SOP", port);
- opos_sop = pd_alt_mode(port, TCPCI_MSG_SOP, USB_VID_INTEL);
-
- /* Clear Thunderbolt related signals */
- pd_dfp_exit_mode(port, TCPCI_MSG_SOP, USB_VID_INTEL, opos_sop);
- set_usb_mux_with_current_data_role(port);
- if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) {
- tbt_active_cable_exit_mode(port);
- } else {
- /*
- * Exit Mode process is complete; go to inactive state.
- */
- tbt_exit_done(port);
- }
- break;
- case TBT_EXIT_SOP:
- set_usb_mux_with_current_data_role(port);
- if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE)
- tbt_active_cable_exit_mode(port);
- else {
- if (TBT_CHK_FLAG(port, TBT_FLAG_RETRY_DONE))
- /* retried enter mode, still failed, give up */
- tbt_exit_done(port);
- else
- tbt_retry_enter_mode(port);
- }
- break;
- case TBT_EXIT_SOP_PRIME_PRIME:
- tbt_prints("exit mode SOP''", port);
- tbt_state[port] = TBT_EXIT_SOP_PRIME;
- set_usb_mux_with_current_data_role(port);
- break;
- case TBT_EXIT_SOP_PRIME:
- tbt_prints("exit mode SOP'", port);
- if (TBT_CHK_FLAG(port, TBT_FLAG_RETRY_DONE)) {
- /*
- * Exit mode process is complete; go to inactive state.
- */
- tbt_exit_done(port);
- opos_sop_prime =
- pd_alt_mode(port, TCPCI_MSG_SOP_PRIME,
- USB_VID_INTEL);
-
- /* Clear Thunderbolt related signals */
- pd_dfp_exit_mode(port, TCPCI_MSG_SOP_PRIME,
- USB_VID_INTEL, opos_sop_prime);
- set_usb_mux_with_current_data_role(port);
- } else {
- tbt_retry_enter_mode(port);
- }
- break;
- case TBT_INACTIVE:
- /*
- * This can occur if the mode is shutdown because
- * the CPU is being turned off, and an exit mode
- * command has been sent.
- */
- break;
- default:
- /* Invalid or unexpected negotiation state */
- CPRINTF("%s called with invalid state %d\n",
- __func__, tbt_state[port]);
- tbt_exit_done(port);
- break;
- }
-}
-
-void intel_vdm_naked(int port, enum tcpci_msg_type type, uint8_t vdm_cmd)
-{
- if (!tbt_response_valid(port, type, "NAK", vdm_cmd))
- return;
-
- switch (tbt_state[port]) {
- case TBT_ENTER_SOP_PRIME:
- case TBT_ENTER_SOP_PRIME_PRIME:
- case TBT_ENTER_SOP:
- /*
- * If a request to enter Thunderbolt mode is NAK'ed, this
- * likely means the partner is already in Thunderbolt alt mode,
- * so request to exit the mode first before retrying the enter
- * command. This can happen if the EC is restarted
- */
- tbt_state[port] = TBT_EXIT_SOP;
- break;
- case TBT_ACTIVE:
- /* Exit SOP got NAK'ed */
- set_usb_mux_with_current_data_role(port);
- if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE)
- tbt_active_cable_exit_mode(port);
- else {
- tbt_prints("exit mode SOP failed", port);
- tbt_state[port] = TBT_INACTIVE;
- TBT_CLR_FLAG(port, TBT_FLAG_RETRY_DONE);
- }
- break;
- case TBT_EXIT_SOP:
- /* Exit SOP got NAK'ed */
- tbt_prints("exit mode SOP failed", port);
- set_usb_mux_with_current_data_role(port);
- if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE)
- tbt_active_cable_exit_mode(port);
- else {
- if (TBT_CHK_FLAG(port, TBT_FLAG_RETRY_DONE))
- /* Retried enter mode, still failed, give up */
- tbt_exit_done(port);
- else
- tbt_retry_enter_mode(port);
- }
- break;
- case TBT_EXIT_SOP_PRIME_PRIME:
- set_usb_mux_with_current_data_role(port);
- tbt_prints("exit mode SOP'' failed", port);
- tbt_state[port] = TBT_EXIT_SOP_PRIME;
- break;
- case TBT_EXIT_SOP_PRIME:
- set_usb_mux_with_current_data_role(port);
- if (TBT_CHK_FLAG(port, TBT_FLAG_RETRY_DONE)) {
- /*
- * Exit mode process is complete; go to inactive state.
- */
- tbt_prints("exit mode SOP' failed", port);
- tbt_exit_done(port);
- } else {
- tbt_retry_enter_mode(port);
- }
- break;
- default:
- CPRINTS("C%d: NAK for cmd %d in state %d", port,
- vdm_cmd, tbt_state[port]);
- tbt_exit_done(port);
- break;
- }
-}
-
-static bool tbt_mode_is_supported(int port, int vdo_count)
-{
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP);
-
- if (!disc->identity.idh.modal_support)
- return false;
-
- if (get_tbt_cable_speed(port) < TBT_SS_U31_GEN1)
- return false;
-
- /*
- * TBT4 PD Discovery Flow Application Notes Revision 0.9:
- * Figure 2: for active cable, SOP' should support
- * SVID USB_VID_INTEL to enter Thunderbolt alt mode
- */
- if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE &&
- !pd_is_mode_discovered_for_svid(
- port, TCPCI_MSG_SOP_PRIME, USB_VID_INTEL))
- return false;
-
- return true;
-}
-
-int tbt_setup_next_vdm(int port, int vdo_count, uint32_t *vdm,
- enum tcpci_msg_type *tx_type)
-{
- struct svdm_amode_data *modep;
- int vdo_count_ret = 0;
- union tbt_mode_resp_cable cable_mode_resp;
-
- *tx_type = TCPCI_MSG_SOP;
-
- if (vdo_count < VDO_MAX_SIZE)
- return -1;
-
- switch (tbt_state[port]) {
- case TBT_START:
- if (!tbt_mode_is_supported(port, vdo_count))
- return 0;
-
- if (!TBT_CHK_FLAG(port, TBT_FLAG_RETRY_DONE))
- tbt_prints("attempt to enter mode", port);
- else
- tbt_prints("retry to enter mode", port);
-
- cable_mode_resp.raw_value =
- pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME);
-
- /* Active cable and LRD cables send Enter Mode SOP' first */
- if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE ||
- cable_mode_resp.tbt_active_passive == TBT_CABLE_ACTIVE) {
- vdo_count_ret = enter_tbt_compat_mode(port,
- TCPCI_MSG_SOP_PRIME, vdm);
- *tx_type = TCPCI_MSG_SOP_PRIME;
- tbt_state[port] = TBT_ENTER_SOP_PRIME;
- } else {
- /* Passive cable send Enter Mode SOP */
- vdo_count_ret =
- enter_tbt_compat_mode(port, TCPCI_MSG_SOP, vdm);
- tbt_state[port] = TBT_ENTER_SOP;
- }
- break;
- case TBT_ENTER_SOP_PRIME:
- vdo_count_ret =
- enter_tbt_compat_mode(port, TCPCI_MSG_SOP_PRIME, vdm);
- *tx_type = TCPCI_MSG_SOP_PRIME;
- break;
- case TBT_ENTER_SOP_PRIME_PRIME:
- vdo_count_ret =
- enter_tbt_compat_mode(
- port, TCPCI_MSG_SOP_PRIME_PRIME, vdm);
- *tx_type = TCPCI_MSG_SOP_PRIME_PRIME;
- break;
- case TBT_ENTER_SOP:
- vdo_count_ret =
- enter_tbt_compat_mode(port, TCPCI_MSG_SOP, vdm);
- break;
- case TBT_EXIT_SOP:
- case TBT_ACTIVE:
- /*
- * Called to exit Thunderbolt alt mode, either when the mode is
- * active and the system is shutting down, or when an initial
- * request to enter the mode is NAK'ed. This can happen if EC
- * is restarted while Thunderbolt mode is active.
- */
- modep = pd_get_amode_data(port,
- TCPCI_MSG_SOP, USB_VID_INTEL);
- if (!(modep && modep->opos))
- return -1;
-
- usb_mux_set_safe_mode_exit(port);
-
- vdm[0] = VDO(USB_VID_INTEL, 1, CMD_EXIT_MODE) |
- VDO_OPOS(modep->opos) |
- VDO_CMDT(CMDT_INIT) |
- VDO_SVDM_VERS(
- pd_get_vdo_ver(port, TCPCI_MSG_SOP));
- vdo_count_ret = 1;
- break;
- case TBT_EXIT_SOP_PRIME_PRIME:
- modep = pd_get_amode_data(port,
- TCPCI_MSG_SOP_PRIME, USB_VID_INTEL);
- if (!(modep && modep->opos))
- return -1;
-
- usb_mux_set_safe_mode_exit(port);
-
- vdm[0] = VDO(USB_VID_INTEL, 1, CMD_EXIT_MODE) |
- VDO_OPOS(modep->opos) |
- VDO_CMDT(CMDT_INIT) |
- VDO_SVDM_VERS(pd_get_vdo_ver(port,
- TCPCI_MSG_SOP_PRIME_PRIME));
- vdo_count_ret = 1;
- *tx_type = TCPCI_MSG_SOP_PRIME_PRIME;
- break;
- case TBT_EXIT_SOP_PRIME:
- modep = pd_get_amode_data(port,
- TCPCI_MSG_SOP_PRIME, USB_VID_INTEL);
- if (!(modep && modep->opos))
- return -1;
-
- usb_mux_set_safe_mode_exit(port);
-
- vdm[0] = VDO(USB_VID_INTEL, 1, CMD_EXIT_MODE) |
- VDO_OPOS(modep->opos) |
- VDO_CMDT(CMDT_INIT) |
- VDO_SVDM_VERS(pd_get_vdo_ver(port,
- TCPCI_MSG_SOP_PRIME));
- vdo_count_ret = 1;
- *tx_type = TCPCI_MSG_SOP_PRIME;
- break;
- case TBT_INACTIVE:
- /* Thunderbolt mode is inactive */
- return 0;
- default:
- CPRINTF("%s called with invalid state %d\n",
- __func__, tbt_state[port]);
- return -1;
- }
-
- return vdo_count_ret;
-}
diff --git a/common/usbc/usb_mode.c b/common/usbc/usb_mode.c
deleted file mode 100644
index b9dc4973bc..0000000000
--- a/common/usbc/usb_mode.c
+++ /dev/null
@@ -1,311 +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.
- */
-
-/*
- * USB4 mode support
- * Refer USB Type-C Cable and Connector Specification Release 2.0 Section 5 and
- * USB Power Delivery Specification Revision 3.0, Version 2.0 Section 6.4.8
- */
-
-#include <stdbool.h>
-#include <stdint.h>
-#include "compile_time_macros.h"
-#include "console.h"
-#include "tcpm/tcpm.h"
-#include "usb_common.h"
-#include "usb_mode.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "usb_pd_dpm.h"
-#include "usb_pd_tcpm.h"
-#include "usb_pe_sm.h"
-#include "usbc_ppc.h"
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#else
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif
-
-enum usb4_mode_status {
- USB4_MODE_FAILURE,
- USB4_MODE_SUCCESS,
-};
-
-enum usb4_states {
- USB4_START,
- USB4_ENTER_SOP,
- USB4_ENTER_SOP_PRIME,
- USB4_ENTER_SOP_PRIME_PRIME,
- USB4_ACTIVE,
- USB4_INACTIVE,
- USB4_STATE_COUNT,
-};
-
-/*
- * USB4 PD flow:
- *
- * Cable type
- * |
- * |-------- Passive ---|---- Active -----|
- * | |
- * USB Highest Speed Structured VDM version
- * | (cable revision)-- <2.0---->|
- * --------|--------|------| | |
- * | | | | >=2.0 |
- * >=Gen3 Gen2 Gen1 USB2.0 | |
- * | | | | VDO version--- <1.3 ---> Modal op? -- N --|
- * Enter USB | | | (B21:23 of | |
- * SOP with | | | Discover ID SOP'- y |
- * Gen3 cable | | Skip Active cable VDO1) | |
- * speed | | USB4 | TBT SVID? -- N --|
- * | | mode >=1.3 | |
- * Is modal op? | entry | y |
- * | | Cable USB4 - N | |
- * y | support? | Gen4 cable? - N - Skip
- * | | | Skip USB4 | USB4
- * Is TBT SVID? -N- Enter | mode entry | mode
- * | USB4 SOP | | entry
- * y with Gen2 y |
- * | cable speed | |
- * | | |
- * Is Discover mode | |
- * SOP' B25? - N - Enter Enter USB4 mode |
- * | USB4 SOP (SOP, SOP', SOP'') |
- * | with speed |
- * y from TBT mode |
- * | SOP' VDO |
- * | |<-- NAK -- Enter mode TBT SOP'<---|
- * |---->Enter TBT SOP'-------NAK------>| | | |
- * | | | | ACK |
- * | ACK | | | |
- * | | | |<-- NAK -- Enter mode TBT SOP'' |
- * | Enter USB4 SOP | | | |
- * | with speed from Exit TBT mode SOP ACK |
- * | TBT mode SOP' VDO | | | |
- * | ACK/NAK Enter USB4 SOP |
- * | | | with speed from |
- * | Exit TBT mode SOP'' TBT mode SOP' VDO |
- * | | | |
- * | ACK/NAK |
- * | | | |
- * | Exit TBT mode SOP' |
- * | | | |
- * | ACK/NAK |
- * | | | |
- * |---- N ----Retry done? -------------| |--------Retry done? ---- N -------|
- * | |
- * y y
- * | |
- * Skip USB4 mode entry Skip USB4 mode entry
- */
-
-static enum usb4_states usb4_state[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-static void usb4_debug_prints(int port, enum usb4_mode_status usb4_status)
-{
- CPRINTS("C%d: USB4: State:%d Status:%d", port, usb4_state[port],
- usb4_status);
-}
-
-bool enter_usb_entry_is_done(int port)
-{
- return usb4_state[port] == USB4_ACTIVE ||
- usb4_state[port] == USB4_INACTIVE;
-}
-
-void usb4_exit_mode_request(int port)
-{
- usb4_state[port] = USB4_START;
- usb_mux_set_safe_mode_exit(port);
- set_usb_mux_with_current_data_role(port);
-}
-
-void enter_usb_init(int port)
-{
- usb4_state[port] = USB4_START;
-}
-
-void enter_usb_failed(int port)
-{
- /*
- * Since Enter USB sets the mux state to SAFE mode, fall back
- * to USB mode on receiving a NAK.
- */
- usb_mux_set(port, USB_PD_MUX_USB_ENABLED, USB_SWITCH_CONNECT,
- polarity_rm_dts(pd_get_polarity(port)));
-
- usb4_debug_prints(port, USB4_MODE_FAILURE);
- usb4_state[port] = USB4_INACTIVE;
-}
-
-static bool enter_usb_response_valid(int port, enum tcpci_msg_type type)
-{
- /*
- * Check for an unexpected response.
- */
- if (get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE &&
- type != TCPCI_MSG_SOP) {
- enter_usb_failed(port);
- return false;
- }
- return true;
-}
-
-bool enter_usb_port_partner_is_capable(int port)
-{
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP);
-
- if (usb4_state[port] == USB4_INACTIVE)
- return false;
-
- if (!PD_PRODUCT_IS_USB4(disc->identity.product_t1.raw_value))
- return false;
-
- return true;
-}
-
-bool enter_usb_cable_is_capable(int port)
-{
- if (get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE) {
- if (get_usb4_cable_speed(port) < USB_R30_SS_U32_U40_GEN1)
- return false;
- } else if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) {
- const struct pd_discovery *disc_sop_prime =
- pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
-
- if (pd_get_vdo_ver(port, TCPCI_MSG_SOP_PRIME) >= VDM_VER20 &&
- disc_sop_prime->identity.product_t1.a_rev30.vdo_ver >=
- VDO_VERSION_1_3) {
- union active_cable_vdo2_rev30 a2_rev30 =
- disc_sop_prime->identity.product_t2.a2_rev30;
- /*
- * For VDM version >= 2.0 and VD0 version is >= 1.3,
- * do not enter USB4 mode if the cable isn't USB4
- * capable.
- */
- if (a2_rev30.usb_40_support == USB4_NOT_SUPPORTED)
- return false;
- /*
- * For VDM version < 2.0 or VDO version < 1.3, do not enter USB4
- * mode if the cable -
- * doesn't support modal operation or
- * doesn't support Intel SVID or
- * doesn't have rounded support.
- */
- } else {
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP);
- union tbt_mode_resp_cable cable_mode_resp = {
- .raw_value = pd_get_tbt_mode_vdo(port,
- TCPCI_MSG_SOP_PRIME) };
-
- if (!disc->identity.idh.modal_support ||
- !pd_is_mode_discovered_for_svid(port,
- TCPCI_MSG_SOP_PRIME, USB_VID_INTEL) ||
- cable_mode_resp.tbt_rounded !=
- TBT_GEN3_GEN4_ROUNDED_NON_ROUNDED)
- return false;
- }
- } else {
- /* Not Emark cable */
- return false;
- }
-
- return true;
-}
-
-void enter_usb_accepted(int port, enum tcpci_msg_type type)
-{
- const struct pd_discovery *disc;
-
- if (!enter_usb_response_valid(port, type))
- return;
-
- switch (usb4_state[port]) {
- case USB4_ENTER_SOP_PRIME:
- disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
- if (disc->identity.product_t1.a_rev20.sop_p_p)
- usb4_state[port] = USB4_ENTER_SOP_PRIME_PRIME;
- else
- usb4_state[port] = USB4_ENTER_SOP;
- break;
- case USB4_ENTER_SOP_PRIME_PRIME:
- usb4_state[port] = USB4_ENTER_SOP;
- break;
- case USB4_ENTER_SOP:
- /* Connect the SBU and USB lines to the connector */
- if (IS_ENABLED(CONFIG_USBC_PPC_SBU))
- ppc_set_sbu(port, 1);
-
- usb4_state[port] = USB4_ACTIVE;
-
- /* Set usb mux to USB4 mode */
- usb_mux_set(port, USB_PD_MUX_USB4_ENABLED, USB_SWITCH_CONNECT,
- polarity_rm_dts(pd_get_polarity(port)));
-
- usb4_debug_prints(port, USB4_MODE_SUCCESS);
- break;
- case USB4_ACTIVE:
- break;
- default:
- enter_usb_failed(port);
- }
-}
-
-void enter_usb_rejected(int port, enum tcpci_msg_type type)
-{
- if (!enter_usb_response_valid(port, type) ||
- usb4_state[port] == USB4_ACTIVE)
- return;
-
- enter_usb_failed(port);
-}
-
-uint32_t enter_usb_setup_next_msg(int port, enum tcpci_msg_type *type)
-{
- const struct pd_discovery *disc_sop_prime;
-
- switch (usb4_state[port]) {
- case USB4_START:
- disc_sop_prime = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
- /*
- * Ref: Tiger Lake Platform PD Controller Interface Requirements
- * for Integrated USBC, section A.2.2: USB4 as DFP.
- * Enter safe mode before sending Enter USB SOP/SOP'/SOP''
- * TODO (b/156749387): Remove once data reset feature is in
- * place.
- */
- usb_mux_set_safe_mode(port);
-
- if (pd_get_vdo_ver(port, TCPCI_MSG_SOP_PRIME) < VDM_VER20 ||
- disc_sop_prime->identity.product_t1.a_rev30.vdo_ver <
- VDO_VERSION_1_3 ||
- get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE) {
- usb4_state[port] = USB4_ENTER_SOP;
- } else {
- usb4_state[port] = USB4_ENTER_SOP_PRIME;
- *type = TCPCI_MSG_SOP_PRIME;
- }
- break;
- case USB4_ENTER_SOP_PRIME:
- *type = TCPCI_MSG_SOP_PRIME;
- break;
- case USB4_ENTER_SOP_PRIME_PRIME:
- *type = TCPCI_MSG_SOP_PRIME_PRIME;
- break;
- case USB4_ENTER_SOP:
- *type = TCPCI_MSG_SOP;
- break;
- case USB4_ACTIVE:
- return -1;
- default:
- return 0;
- }
- return get_enter_usb_msg_payload(port);
-}
diff --git a/common/usbc/usb_pd_console.c b/common/usbc/usb_pd_console.c
deleted file mode 100644
index bbee776611..0000000000
--- a/common/usbc/usb_pd_console.c
+++ /dev/null
@@ -1,212 +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.
- */
-
-#include "common.h"
-#include "console.h"
-#include "usb_common.h"
-#include "usb_pd_timer.h"
-#include "usb_pe_sm.h"
-#include "usb_prl_sm.h"
-#include "usb_tc_sm.h"
-#include "usb_pd.h"
-#include "util.h"
-
-test_export_static int command_pd(int argc, char **argv)
-{
- int port;
- char *e;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- if (!strcasecmp(argv[1], "dump")) {
- if (argc >= 3) {
- int level = strtoi(argv[2], &e, 10);
-
- if (*e)
- return EC_ERROR_PARAM2;
-
- if (level < DEBUG_DISABLE)
- level = DEBUG_DISABLE;
- else if (level > DEBUG_LEVEL_MAX)
- level = DEBUG_LEVEL_MAX;
-
- prl_set_debug_level(level);
- pe_set_debug_level(level);
- tc_set_debug_level(level);
- ccprintf("debug=%d\n", level);
- return EC_SUCCESS;
- }
- } else if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC) &&
- !strcasecmp(argv[1], "trysrc")) {
- enum try_src_override_t ov = tc_get_try_src_override();
-
- if (argc >= 3) {
- ov = strtoi(argv[2], &e, 10);
- if (*e || ov > TRY_SRC_NO_OVERRIDE)
- return EC_ERROR_PARAM3;
- tc_try_src_override(ov);
- }
-
- if (ov == TRY_SRC_NO_OVERRIDE)
- ccprintf("Try.SRC System controlled\n");
- else
- ccprintf("Try.SRC Forced %s\n", ov ? "ON" : "OFF");
-
- return EC_SUCCESS;
- } else if (!strcasecmp(argv[1], "version")) {
- ccprintf("%d\n", PD_STACK_VERSION);
- return EC_SUCCESS;
- }
-
- /* command: pd <port> <subcmd> [args] */
- port = strtoi(argv[1], &e, 10);
- if (argc < 3)
- return EC_ERROR_PARAM_COUNT;
-
- if (*e || port >= CONFIG_USB_PD_PORT_MAX_COUNT)
- return EC_ERROR_PARAM2;
-
- if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE)) {
- if (!strcasecmp(argv[2], "tx")) {
- pd_dpm_request(port, DPM_REQUEST_SNK_STARTUP);
- } else if (!strcasecmp(argv[2], "charger")) {
- pd_dpm_request(port, DPM_REQUEST_SRC_STARTUP);
- } else if (!strcasecmp(argv[2], "dev")) {
- int max_volt;
-
- if (argc >= 4) {
- max_volt = strtoi(argv[3], &e, 10) * 1000;
- if (*e)
- return EC_ERROR_PARAM3;
- } else {
- max_volt = pd_get_max_voltage();
- }
- pd_request_source_voltage(port, max_volt);
- pd_dpm_request(port, DPM_REQUEST_NEW_POWER_LEVEL);
- ccprintf("max req: %dmV\n", max_volt);
- } else if (!strcasecmp(argv[2], "disable")) {
- pd_comm_enable(port, 0);
- ccprintf("Port C%d disable\n", port);
- return EC_SUCCESS;
- } else if (!strcasecmp(argv[2], "enable")) {
- pd_comm_enable(port, 1);
- ccprintf("Port C%d enabled\n", port);
- return EC_SUCCESS;
- } else if (!strcasecmp(argv[2], "hard")) {
- pd_dpm_request(port, DPM_REQUEST_HARD_RESET_SEND);
- } else if (!strcasecmp(argv[2], "soft")) {
- pd_dpm_request(port, DPM_REQUEST_SOFT_RESET_SEND);
- } else if (!strcasecmp(argv[2], "swap")) {
- if (argc < 4)
- return EC_ERROR_PARAM_COUNT;
-
- if (!strcasecmp(argv[3], "power"))
- pd_dpm_request(port, DPM_REQUEST_PR_SWAP);
- else if (!strcasecmp(argv[3], "data"))
- pd_dpm_request(port, DPM_REQUEST_DR_SWAP);
- else if (IS_ENABLED(CONFIG_USBC_VCONN_SWAP) &&
- !strcasecmp(argv[3], "vconn"))
- pd_dpm_request(port, DPM_REQUEST_VCONN_SWAP);
- else
- return EC_ERROR_PARAM3;
- } else if (!strcasecmp(argv[2], "dualrole")) {
- if (argc < 4) {
- cflush();
- ccprintf("dual-role toggling: ");
- switch (pd_get_dual_role(port)) {
- case PD_DRP_TOGGLE_ON:
- ccprintf("on\n");
- break;
- case PD_DRP_TOGGLE_OFF:
- ccprintf("off\n");
- break;
- case PD_DRP_FREEZE:
- ccprintf("freeze\n");
- break;
- case PD_DRP_FORCE_SINK:
- ccprintf("force sink\n");
- break;
- case PD_DRP_FORCE_SOURCE:
- ccprintf("force source\n");
- break;
- cflush();
- }
- } else {
- if (!strcasecmp(argv[3], "on"))
- pd_set_dual_role(port,
- PD_DRP_TOGGLE_ON);
- else if (!strcasecmp(argv[3], "off"))
- pd_set_dual_role(port,
- PD_DRP_TOGGLE_OFF);
- else if (!strcasecmp(argv[3], "freeze"))
- pd_set_dual_role(port, PD_DRP_FREEZE);
- else if (!strcasecmp(argv[3], "sink"))
- pd_set_dual_role(port,
- PD_DRP_FORCE_SINK);
- else if (!strcasecmp(argv[3], "source"))
- pd_set_dual_role(port,
- PD_DRP_FORCE_SOURCE);
- else
- return EC_ERROR_PARAM4;
- }
- return EC_SUCCESS;
- }
- }
-
- if (!strcasecmp(argv[2], "state")) {
- cflush();
- ccprintf("Port C%d CC%d, %s - Role: %s-%s",
- port, pd_get_polarity(port) + 1,
- pd_comm_is_enabled(port) ? "Enable" : "Disable",
- pd_get_power_role(port) ==
- PD_ROLE_SOURCE ? "SRC" : "SNK",
- pd_get_data_role(port) == PD_ROLE_DFP ? "DFP" : "UFP");
-
- if (IS_ENABLED(CONFIG_USBC_VCONN))
- ccprintf("%s ", tc_is_vconn_src(port) ? "-VC" : "");
-
- ccprintf("TC State: %s, Flags: 0x%04x",
- tc_get_current_state(port),
- tc_get_flags(port));
-
- if (IS_ENABLED(CONFIG_USB_PE_SM))
- ccprintf(" PE State: %s, Flags: 0x%04x\n",
- pe_get_current_state(port),
- pe_get_flags(port));
- else
- ccprintf("\n");
-
- cflush();
- } else if (!strcasecmp(argv[2], "srccaps")) {
- pd_srccaps_dump(port);
- }
-
- if (IS_ENABLED(CONFIG_CMD_PD_TIMER) &&
- !strcasecmp(argv[2], "timer")) {
- pd_timer_dump(port);
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(pd, command_pd,
- "version"
- "\ndump [0|1|2|3]"
-#ifdef CONFIG_USB_PD_TRY_SRC
- "\ntrysrc [0|1|2]"
-#endif
- "\n\t<port> state"
- "\n\t<port> srccaps"
-#ifdef CONFIG_CMD_PD_TIMER
- "\n\t<port> timer"
-#endif /* CONFIG_CMD_PD_TIMER */
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- "|tx|charger|dev"
- "\n\t<port> disable|enable|soft|hard"
- "\n\t<port> dualrole [on|off|freeze|sink|source]"
- "\n\t<port> swap [power|data|vconn]"
-#endif /* CONFIG_USB_PD_DUAL_ROLE */
- ,
- "USB PD");
diff --git a/common/usbc/usb_pd_dp_ufp.c b/common/usbc/usb_pd_dp_ufp.c
deleted file mode 100644
index 0009b5c710..0000000000
--- a/common/usbc/usb_pd_dp_ufp.c
+++ /dev/null
@@ -1,448 +0,0 @@
-/* Copyright 2021 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.
- */
-
-/*
- * Functions required for UFP_D operation
- */
-
-#include "console.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "system.h"
-#include "task.h"
-#include "usb_pd.h"
-#include "usb_pd_dp_ufp.h"
-
-
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-
-enum hpd_state {
- LOW_WAIT,
- HIGH_CHECK,
- HIGH_WAIT,
- LOW_CHECK,
- IRQ_CHECK,
-};
-
-#define EDGE_QUEUE_DEPTH BIT(3)
-#define EDGE_QUEUE_MASK (EDGE_QUEUE_DEPTH - 1)
-#define HPD_QUEUE_DEPTH BIT(2)
-#define HPD_QUEUE_MASK (HPD_QUEUE_DEPTH - 1)
-#define HPD_T_IRQ_MIN_PULSE 250
-#define HPD_T_IRQ_MAX_PULSE (2 * MSEC)
-#define HPD_T_MIN_DP_ATTEN (10 * MSEC)
-
-struct hpd_mark {
- int level;
- uint64_t ts;
-};
-
-struct hpd_edge {
- int overflow;
- uint32_t head;
- uint32_t tail;
- struct hpd_mark buffer[EDGE_QUEUE_DEPTH];
-};
-
-struct hpd_info {
- enum hpd_state state;
- int count;
- int send_enable;
- uint64_t timer;
- uint64_t last_send_ts;
- enum hpd_event queue[HPD_QUEUE_DEPTH];
- struct hpd_edge edges;
-};
-
-static struct hpd_info hpd;
-static struct mutex hpd_mutex;
-
-static int alt_dp_mode_opos[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-void pd_ufp_set_dp_opos(int port, int opos)
-{
- alt_dp_mode_opos[port] = opos;
-}
-
-int pd_ufp_get_dp_opos(int port)
-{
- return alt_dp_mode_opos[port];
-}
-
-void pd_ufp_enable_hpd_send(int port)
-{
- /*
- * This control is used ensure that a DP_ATTENTION message is not sent
- * to the DFP-D before a DP_CONFIG messaage has been received. This
- * control is not strictly required by the spec, but some port partners
- * will get confused if DP_ATTENTION is sent prior to DP_CONFIG.
- */
- hpd.send_enable = 1;
-}
-
-static void hpd_to_dp_attention(void)
-{
- int port = hpd_config.port;
- int evt_index = hpd.count - 1;
- uint32_t vdm[2];
- uint32_t svdm_header;
- enum hpd_event evt;
- int opos = pd_ufp_get_dp_opos(port);
-
- if (!opos)
- return;
-
- /* Get the next hpd event from the queue */
- evt = hpd.queue[evt_index];
- /* Save timestamp of when most recent DP attention message was sent */
- hpd.last_send_ts = get_time().val;
-
- /*
- * Construct DP Attention message. This consists of the VDM header and
- * the DP_STATUS VDO.
- */
- svdm_header = VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP)) |
- VDO_OPOS(opos) | CMD_ATTENTION;
- vdm[0] = VDO(USB_SID_DISPLAYPORT, 1, svdm_header);
-
- vdm[1] = VDO_DP_STATUS((evt == hpd_irq), /* IRQ_HPD */
- (evt != hpd_low), /* HPD_HI|LOW */
- 0, /* request exit DP */
- 0, /* request exit USB */
- dock_get_mf_preference(), /* MF pref */
- 1, /* enabled */
- 0, /* power low */
- 0x2);
-
- /* Send request to DPM to send an attention VDM */
- pd_request_vdm_attention(port, vdm, ARRAY_SIZE(vdm));
-
- /* If there are still events, need to shift the buffer */
- if (--hpd.count) {
- int i;
-
- for (i = 0; i < hpd.count; i++)
- hpd.queue[i] = hpd.queue[i + 1];
- }
-}
-
-static void hpd_queue_event(enum hpd_event evt)
-{
- /*
- * HPD events are put into a queue. However, this queue is not a typical
- * FIFO queue. Instead there are special rules based on which type of
- * event is being added.
- * HPD_LOW -> always resets the queue and must be in slot 0
- * HPD_HIGH -> must follow a HPD_LOW, so can only be in slot 0 or
- * slot 1.
- * HPD_IRQ -> There shall never be more than 2 HPD_IRQ events
- * stored in the queue and HPD_IRQ must follow HPD_HIGH
- *
- * Worst case for queueing HPD events is 4 events in the queue:
- * 0 - HPD_LOW
- * 1 - HPD_HIGH
- * 2 - HPD_IRQ
- * 3 - HPD_IRQ
- *
- * The above rules mean that HPD_LOW and HPD_HIGH events can always be
- * added to the queue since high must follow low and a low event resets
- * the queue. HPD_IRQ events are checked to make sure that they don't
- * overflow the queue and to ensure that no more than 2 hpd_irq events
- * are kept in the queue.
- */
- if (evt == hpd_irq) {
- if ((hpd.count >= HPD_QUEUE_DEPTH) || ((hpd.count >= 2) &&
- (hpd.queue[hpd.count - 2] == hpd_irq))) {
- CPRINTS("hpd: discard hpd: count - %d",
- hpd.count);
- return;
- }
- }
-
- if (evt == hpd_low) {
- hpd.count = 0;
- }
-
- /* Add event to the queue */
- hpd.queue[hpd.count++] = evt;
-}
-
-static void hpd_to_pd_converter(int level, uint64_t ts)
-{
- /*
- * HPD edges are marked in the irq routine. The converter state machine
- * runs in the hooks task and so there will be some delay between when
- * the edge was captured and when that edge is processed here in the
- * state machine. This means that the delitch timer (250 uSec) may have
- * already expired or is about to expire.
- *
- * If transitioning to timing dependent state, need to ensure the state
- * machine is executed again. All timers are relative to the ts value
- * passed into this routine. The timestamps passed into this routine
- * are either the values latched in the irq routine, or the current
- * time latched by the calling function. From the perspective of the
- * state machine, ts represents the current time.
- *
- * Note that all hpd queue events are contingent on detecting edges
- * on the incoming hpd gpio signal. The hpd->dp attention converter is
- * enabled/disabled as part of the svdm dp enter/exit response handler
- * functions. When the converter is disabled, gpio interrupts for the
- * hpd gpio signal are disabled so it will never execute, unless the
- * converter is enabled, and the converter is only enabled when the
- * UFP-D is actively in ALT-DP mode.
- */
- switch (hpd.state) {
- case LOW_WAIT:
- /*
- * In this state only expected event is a level change from low
- * to high.
- */
- if (level) {
- hpd.state = HIGH_CHECK;
- hpd.timer = ts + HPD_T_IRQ_MIN_PULSE;
- }
- break;
- case HIGH_CHECK:
- /*
- * In this state if level is high and deglitch timer is
- * exceeded, then state advances to HIGH_WAIT, otherwise return
- * to LOW_WAIT state.
- */
- if (!level || (ts <= hpd.timer)) {
- hpd.state = LOW_WAIT;
- } else {
- hpd.state = HIGH_WAIT;
- hpd_queue_event(hpd_high);
- }
- break;
- case HIGH_WAIT:
- /*
- * In this state, only expected event is a level change from
- * high to low. If current level is low, then advance to
- * LOW_CHECK for deglitch checking.
- */
- if (!level) {
- hpd.state = LOW_CHECK;
- hpd.timer = ts + HPD_T_IRQ_MIN_PULSE;
- }
- break;
- case LOW_CHECK:
- /*
- * This state is used to deglitch high->low level
- * change. However, due to processing latency, it's possible to
- * detect hpd_irq event if level is high and low pulse width was
- * valid.
- */
- if (!level) {
- /* Still low, now wait for IRQ or LOW determination */
- hpd.timer = ts + (HPD_T_IRQ_MAX_PULSE -
- HPD_T_IRQ_MIN_PULSE);
- hpd.state = IRQ_CHECK;
-
- } else {
- uint64_t irq_ts = hpd.timer + HPD_T_IRQ_MAX_PULSE -
- HPD_T_IRQ_MIN_PULSE;
- /*
- * If hpd is high now, this must have been an edge
- * event, but still need to determine if the pulse width
- * is longer than hpd_irq min pulse width. State will
- * advance to HIGH_WAIT, but if pulse width is < 2 msec,
- * must send hpd_irq event.
- */
- if ((ts >= hpd.timer) && (ts <= irq_ts)) {
- /* hpd irq detected */
- hpd_queue_event(hpd_irq);
- }
- hpd.state = HIGH_WAIT;
- }
- break;
- case IRQ_CHECK:
- /*
- * In this state deglitch time has already passed. If current
- * level is low and hpd_irq timer has expired, then go to
- * LOW_WAIT as hpd_low event has been detected. If level is high
- * and low pulse is < hpd_irq, hpd_irq event has been detected.
- */
- if (level) {
- hpd.state = HIGH_WAIT;
- if (ts <= hpd.timer) {
- hpd_queue_event(hpd_irq);
- }
- } else if (ts > hpd.timer) {
- hpd.state = LOW_WAIT;
- hpd_queue_event(hpd_low);
- }
- break;
- }
-}
-
-static void manage_hpd(void);
-DECLARE_DEFERRED(manage_hpd);
-
-static void manage_hpd(void)
-{
- int level;
- uint64_t ts = get_time().val;
- uint32_t num_hpd_events = (hpd.edges.head - hpd.edges.tail) &
- EDGE_QUEUE_MASK;
-
- /*
- * HPD edges are detected via GPIO interrupts. The ISR routine adds edge
- * info to a queue and scheudles this routine. If this routine is called
- * without a new edge detected, then it is being called due to a timer
- * event.
- */
-
- /* First check to see overflow condition has occurred */
- if (hpd.edges.overflow) {
- /* Disable hpd interrupts */
- usb_pd_hpd_converter_enable(0);
- /* Re-enable hpd converter */
- usb_pd_hpd_converter_enable(1);
- }
-
- if (num_hpd_events) {
- while(num_hpd_events-- > 0) {
- int idx = hpd.edges.tail;
-
- level = hpd.edges.buffer[idx].level;
- ts = hpd.edges.buffer[idx].ts;
-
- hpd_to_pd_converter(level, ts);
- hpd.edges.tail = (hpd.edges.tail + 1) & EDGE_QUEUE_MASK;
- }
- } else {
- /* no new edge event, so get current time and level */
- level = gpio_get_level(hpd_config.signal);
- ts = get_time().val;
- hpd_to_pd_converter(level, ts);
- }
-
- /*
- * If min time spacing requirement is exceeded and a hpd_event is
- * queued, then send DP_ATTENTION message.
- */
- if (hpd.count > 0) {
- /*
- * If at least one hpd event is pending in the queue, send
- * a DP_ATTENTION message if a DP_CONFIG message has been
- * received and have passed the minimum spacing interval.
- */
- if (hpd.send_enable &&
- ((get_time().val - hpd.last_send_ts) >
- HPD_T_MIN_DP_ATTEN)) {
- /* Generate DP_ATTENTION event pending in queue */
- hpd_to_dp_attention();
- } else {
- uint32_t callback_us;
-
- /*
- * Need to wait until until min spacing requirement of
- * DP attention messages. Set callback time to the min
- * value required. This callback time could be changed
- * based on hpd interrupts.
- *
- * This wait is also used to prevent a DP_ATTENTION
- * message from being sent before at least one DP_CONFIG
- * message has been received. If DP_ATTENTION messages
- * need to be delayed for this reason, then just wait
- * the minimum time spacing.
- */
- callback_us = HPD_T_MIN_DP_ATTEN -
- (get_time().val - hpd.last_send_ts);
- if (callback_us <= 0 ||
- callback_us > HPD_T_MIN_DP_ATTEN)
- callback_us = HPD_T_MIN_DP_ATTEN;
- hook_call_deferred(&manage_hpd_data, callback_us);
- }
- }
-
- /*
- * Because of the delay between gpio edge irq, and when those edge
- * events are processed here, all timers must be done relative to the
- * timing marker stored in the hpd edge queue. If the state machine
- * required a new timer, then hpd.timer will be advanced relative to the
- * ts that was passed into the state machine.
- *
- * If the deglitch timer is active, then it can likely already have been
- * expired when the edge gets processed. So if the timer is active the
- * deferred callback must be requested.
- *.
- */
- if (hpd.timer > ts) {
- uint64_t callback_us = 0;
- uint64_t now = get_time().val;
-
- /* If timer is in the future, adjust the callback timer */
- if (now < hpd.timer)
- callback_us = (hpd.timer - now) & 0xffffffff;
-
- hook_call_deferred(&manage_hpd_data, callback_us);
- }
-}
-
-void usb_pd_hpd_converter_enable(int enable)
-{
- /*
- * The hpd converter should be enabled as part of the UFP-D enter mode
- * response function. Likewise, the converter should be disabled by the
- * exit mode function. In addition, the coverter may get disabled so
- * that it can be reset in the case that the input gpio edges queue
- * overflows. A muxtex must be used here since this function may be
- * called from the PD task (enter/exit response mode functions) or from
- * the hpd event handler state machine (hook task).
- */
- mutex_lock(&hpd_mutex);
-
- if (enable) {
- gpio_disable_interrupt(hpd_config.signal);
- /* Reset HPD event queue */
- hpd.state = LOW_WAIT;
- hpd.count = 0;
- hpd.timer = 0;
- hpd.last_send_ts = 0;
- hpd.send_enable = 0;
-
- /* Reset hpd signal edges queue */
- hpd.edges.head = 0;
- hpd.edges.tail = 0;
- hpd.edges.overflow = 0;
-
- /* If signal is high, need to ensure state machine executes */
- if (gpio_get_level(hpd_config.signal))
- hook_call_deferred(&manage_hpd_data, 0);
-
- /* Enable hpd edge detection */
- gpio_enable_interrupt(hpd_config.signal);
- } else {
- gpio_disable_interrupt(hpd_config.signal);
- hook_call_deferred(&manage_hpd_data, -1);
- }
-
- mutex_unlock(&hpd_mutex);
-}
-
-void usb_pd_hpd_edge_event(int signal)
-{
- int next_head = (hpd.edges.head + 1) & EDGE_QUEUE_MASK;
- struct hpd_mark mark;
-
- /* Get current timestamp and level */
- mark.ts = get_time().val;
- mark.level = gpio_get_level(hpd_config.signal);
-
- /* Add this edge to the buffer if there is space */
- if (next_head != hpd.edges.tail) {
- hpd.edges.buffer[hpd.edges.head].ts = mark.ts;
- hpd.edges.buffer[hpd.edges.head].level = mark.level;
- hpd.edges.head = next_head;
- } else {
- /* Edge queue is overflowing, need to reset the converter */
- hpd.edges.overflow = 1;
- }
- /* Schedule HPD state machine to run ASAP */
- hook_call_deferred(&manage_hpd_data, 0);
-}
diff --git a/common/usbc/usb_pd_dpm.c b/common/usbc/usb_pd_dpm.c
deleted file mode 100644
index eb2dfc52c0..0000000000
--- a/common/usbc/usb_pd_dpm.c
+++ /dev/null
@@ -1,704 +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.
- */
-
-/*
- * Device Policy Manager implementation
- * Refer to USB PD 3.0 spec, version 2.0, sections 8.2 and 8.3
- */
-
-#include "charge_state.h"
-#include "compile_time_macros.h"
-#include "console.h"
-#include "ec_commands.h"
-#include "hooks.h"
-#include "system.h"
-#include "task.h"
-#include "tcpm/tcpm.h"
-#include "usb_dp_alt_mode.h"
-#include "usb_mode.h"
-#include "usb_pd.h"
-#include "usb_pd_dpm.h"
-#include "usb_pd_tcpm.h"
-#include "usb_tbt_alt_mode.h"
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#else
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif
-
-/* Max Attention length is header + 1 VDO */
-#define DPM_ATTENION_MAX_VDO 2
-
-static struct {
- uint32_t flags;
- uint32_t vdm_attention[DPM_ATTENION_MAX_VDO];
- int vdm_cnt;
- mutex_t vdm_attention_mutex;
-} dpm[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-#define DPM_SET_FLAG(port, flag) atomic_or(&dpm[(port)].flags, (flag))
-#define DPM_CLR_FLAG(port, flag) atomic_clear_bits(&dpm[(port)].flags, (flag))
-#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)
-
-#ifdef CONFIG_ZEPHYR
-static int init_vdm_attention_mutex(const struct device *dev)
-{
- int port;
-
- ARG_UNUSED(dev);
-
- for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++)
- k_mutex_init(&dpm[port].vdm_attention_mutex);
-
- return 0;
-}
-SYS_INIT(init_vdm_attention_mutex, POST_KERNEL, 50);
-#endif /* CONFIG_ZEPHYR */
-
-enum ec_status pd_request_vdm_attention(int port, const uint32_t *data,
- int vdo_count)
-{
- mutex_lock(&dpm[port].vdm_attention_mutex);
-
- /* Only one Attention message may be pending */
- if (DPM_CHK_FLAG(port, DPM_FLAG_SEND_ATTENTION)) {
- mutex_unlock(&dpm[port].vdm_attention_mutex);
- return EC_RES_UNAVAILABLE;
- }
-
- /* SVDM Attention message must be 1 or 2 VDOs in length */
- if (!vdo_count || (vdo_count > DPM_ATTENION_MAX_VDO)) {
- mutex_unlock(&dpm[port].vdm_attention_mutex);
- return EC_RES_INVALID_PARAM;
- }
-
- /* Save contents of Attention message */
- memcpy(dpm[port].vdm_attention, data, vdo_count * sizeof(uint32_t));
- dpm[port].vdm_cnt = vdo_count;
-
- /*
- * Indicate to DPM that an Attention message needs to be sent. This flag
- * will be cleared when the Attention message is sent to the policy
- * engine.
- */
- DPM_SET_FLAG(port, DPM_FLAG_SEND_ATTENTION);
-
- mutex_unlock(&dpm[port].vdm_attention_mutex);
-
- return EC_RES_SUCCESS;
-}
-
-enum ec_status pd_request_enter_mode(int port, enum typec_mode mode)
-{
- if (port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- /* Only one enter request may be active at a time. */
- if (DPM_CHK_FLAG(port, DPM_FLAG_ENTER_DP |
- DPM_FLAG_ENTER_TBT |
- DPM_FLAG_ENTER_USB4))
- return EC_RES_BUSY;
-
- switch (mode) {
- case TYPEC_MODE_DP:
- DPM_SET_FLAG(port, DPM_FLAG_ENTER_DP);
- break;
-#ifdef CONFIG_USB_PD_TBT_COMPAT_MODE
- case TYPEC_MODE_TBT:
- DPM_SET_FLAG(port, DPM_FLAG_ENTER_TBT);
- break;
-#endif /* CONFIG_USB_PD_TBT_COMPAT_MODE */
-#ifdef CONFIG_USB_PD_USB4
- case TYPEC_MODE_USB4:
- DPM_SET_FLAG(port, DPM_FLAG_ENTER_USB4);
- break;
-#endif
- default:
- return EC_RES_INVALID_PARAM;
- }
-
- DPM_CLR_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE);
- DPM_CLR_FLAG(port, DPM_FLAG_EXIT_REQUEST);
-
- return EC_RES_SUCCESS;
-}
-
-void dpm_init(int port)
-{
- dpm[port].flags = 0;
-}
-
-static void dpm_set_mode_entry_done(int port)
-{
- DPM_SET_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE);
- DPM_CLR_FLAG(port, DPM_FLAG_ENTER_DP | DPM_FLAG_ENTER_TBT |
- DPM_FLAG_ENTER_USB4);
-}
-
-void dpm_set_mode_exit_request(int port)
-{
- DPM_SET_FLAG(port, DPM_FLAG_EXIT_REQUEST);
-}
-
-static void dpm_clear_mode_exit_request(int port)
-{
- DPM_CLR_FLAG(port, DPM_FLAG_EXIT_REQUEST);
-}
-
-/*
- * Returns true if the current policy requests that the EC try to enter this
- * mode on this port. If the EC is in charge of policy, the answer is always
- * yes.
- */
-static bool dpm_mode_entry_requested(int port, enum typec_mode mode)
-{
- /* If the AP isn't controlling policy, the EC is. */
- if (!IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY))
- return true;
-
- switch (mode) {
- case TYPEC_MODE_DP:
- return !!DPM_CHK_FLAG(port, DPM_FLAG_ENTER_DP);
- case TYPEC_MODE_TBT:
- return !!DPM_CHK_FLAG(port, DPM_FLAG_ENTER_TBT);
- case TYPEC_MODE_USB4:
- return !!DPM_CHK_FLAG(port, DPM_FLAG_ENTER_USB4);
- default:
- return false;
- }
-}
-
-void dpm_vdm_acked(int port, enum tcpci_msg_type type, int vdo_count,
- uint32_t *vdm)
-{
- const uint16_t svid = PD_VDO_VID(vdm[0]);
-
- assert(vdo_count >= 1);
-
- switch (svid) {
- case USB_SID_DISPLAYPORT:
- dp_vdm_acked(port, type, vdo_count, vdm);
- break;
- case USB_VID_INTEL:
- if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE)) {
- intel_vdm_acked(port, type, vdo_count, vdm);
- break;
- }
- default:
- CPRINTS("C%d: Received unexpected VDM ACK for SVID %d", port,
- svid);
- }
-}
-
-void dpm_vdm_naked(int port, enum tcpci_msg_type type, uint16_t svid,
- uint8_t vdm_cmd)
-{
- switch (svid) {
- case USB_SID_DISPLAYPORT:
- dp_vdm_naked(port, type, vdm_cmd);
- break;
- case USB_VID_INTEL:
- if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE)) {
- intel_vdm_naked(port, type, vdm_cmd);
- break;
- }
- default:
- CPRINTS("C%d: Received unexpected VDM NAK for SVID %d", port,
- svid);
- }
-}
-
-/*
- * Requests that the PE send one VDM, whichever is next in the mode entry
- * sequence. This only happens if preconditions for mode entry are met. If
- * CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY is enabled, this function waits for the
- * AP to direct mode entry.
- */
-static void dpm_attempt_mode_entry(int port)
-{
- int vdo_count = 0;
- uint32_t vdm[VDO_MAX_SIZE];
- enum tcpci_msg_type tx_type = TCPCI_MSG_SOP;
- bool enter_mode_requested =
- IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY) ? false : true;
-
- if (pd_get_data_role(port) != PD_ROLE_DFP) {
- if (DPM_CHK_FLAG(port, DPM_FLAG_ENTER_DP |
- DPM_FLAG_ENTER_TBT |
- DPM_FLAG_ENTER_USB4))
- DPM_CLR_FLAG(port, DPM_FLAG_ENTER_DP |
- DPM_FLAG_ENTER_TBT |
- DPM_FLAG_ENTER_USB4);
- /*
- * TODO(b/168030639): Notify the AP that the enter mode request
- * failed.
- */
- return;
- }
-
-#ifdef HAS_TASK_CHIPSET
- /*
- * Do not try to enter mode while CPU is off.
- * CPU transitions (e.g b/158634281) can occur during the discovery
- * phase or during enter/exit negotiations, and the state
- * of the modes can get out of sync, causing the attempt to
- * enter the mode to fail prematurely.
- */
- if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF))
- return;
-#endif
- /*
- * If discovery has not occurred for modes, do not attempt to switch
- * to alt mode.
- */
- if (pd_get_svids_discovery(port, TCPCI_MSG_SOP) != PD_DISC_COMPLETE ||
- pd_get_modes_discovery(port, TCPCI_MSG_SOP) != PD_DISC_COMPLETE)
- return;
-
- if (dp_entry_is_done(port) ||
- (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) &&
- tbt_entry_is_done(port)) ||
- (IS_ENABLED(CONFIG_USB_PD_USB4) && enter_usb_entry_is_done(port))) {
- dpm_set_mode_entry_done(port);
- return;
- }
-
- /* Check if port, port partner and cable support USB4. */
- if (IS_ENABLED(CONFIG_USB_PD_USB4) &&
- board_is_tbt_usb4_port(port) &&
- enter_usb_port_partner_is_capable(port) &&
- enter_usb_cable_is_capable(port) &&
- dpm_mode_entry_requested(port, TYPEC_MODE_USB4)) {
- /*
- * For certain cables, enter Thunderbolt alt mode with the
- * cable and USB4 mode with the port partner.
- */
- if (tbt_cable_entry_required_for_usb4(port)) {
- vdo_count = tbt_setup_next_vdm(port,
- ARRAY_SIZE(vdm), vdm, &tx_type);
- } else {
- pd_dpm_request(port, DPM_REQUEST_ENTER_USB);
- return;
- }
- }
-
- /* If not, check if they support Thunderbolt alt mode. */
- if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) &&
- board_is_tbt_usb4_port(port) &&
- pd_is_mode_discovered_for_svid(port, TCPCI_MSG_SOP,
- USB_VID_INTEL) &&
- dpm_mode_entry_requested(port, TYPEC_MODE_TBT)) {
- enter_mode_requested = true;
- vdo_count = tbt_setup_next_vdm(port,
- ARRAY_SIZE(vdm), vdm, &tx_type);
- }
-
- /* If not, check if they support DisplayPort alt mode. */
- if (vdo_count == 0 && !DPM_CHK_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE) &&
- pd_is_mode_discovered_for_svid(port, TCPCI_MSG_SOP,
- USB_SID_DISPLAYPORT) &&
- dpm_mode_entry_requested(port, TYPEC_MODE_DP)) {
- enter_mode_requested = true;
- vdo_count = dp_setup_next_vdm(port, ARRAY_SIZE(vdm), vdm);
- }
-
- /*
- * If the PE didn't discover any supported (requested) alternate mode,
- * just mark setup done and get out of here.
- */
- if (vdo_count == 0 && !DPM_CHK_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE)) {
- if (enter_mode_requested) {
- /*
- * TODO(b/168030639): Notify the AP that mode entry
- * failed.
- */
- CPRINTS("C%d: No supported alt mode discovered", port);
- }
- /*
- * If the AP did not request mode entry, it may do so in the
- * future, but the DPM is done trying for now.
- */
- dpm_set_mode_entry_done(port);
- return;
- }
-
- if (vdo_count < 0) {
- dpm_set_mode_entry_done(port);
- CPRINTS("C%d: Couldn't construct alt mode VDM", port);
- return;
- }
-
- /*
- * TODO(b/155890173): Provide a host command to request that the PE send
- * an arbitrary VDM via this mechanism.
- */
- if (!pd_setup_vdm_request(port, tx_type, vdm, vdo_count)) {
- dpm_set_mode_entry_done(port);
- return;
- }
-
- pd_dpm_request(port, DPM_REQUEST_VDM);
-}
-
-static void dpm_attempt_mode_exit(int port)
-{
- uint32_t vdm = 0;
- int vdo_count = 0;
- enum tcpci_msg_type tx_type = TCPCI_MSG_SOP;
-
- if (IS_ENABLED(CONFIG_USB_PD_USB4) &&
- enter_usb_entry_is_done(port)) {
- CPRINTS("C%d: USB4 teardown", port);
- usb4_exit_mode_request(port);
- }
- if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) &&
- tbt_is_active(port)) {
- /*
- * When the port is in USB4 mode and receives an exit request,
- * it leaves USB4 SOP in active state.
- * TODO(b/156749387): Support Data Reset for exiting USB4 SOP.
- */
- CPRINTS("C%d: TBT teardown", port);
- tbt_exit_mode_request(port);
- vdo_count = tbt_setup_next_vdm(port, VDO_MAX_SIZE, &vdm,
- &tx_type);
- } else if (dp_is_active(port)) {
- CPRINTS("C%d: DP teardown", port);
- vdo_count = dp_setup_next_vdm(port, VDO_MAX_SIZE, &vdm);
- } else {
- /* Clear exit mode request */
- dpm_clear_mode_exit_request(port);
- return;
- }
-
- if (!pd_setup_vdm_request(port, tx_type, &vdm, vdo_count)) {
- dpm_clear_mode_exit_request(port);
- return;
- }
-
- pd_dpm_request(port, DPM_REQUEST_VDM);
-}
-
-static void dpm_send_attention_vdm(int port)
-{
- /* Set up VDM ATTEN msg that was passed in previously */
- if (pd_setup_vdm_request(port, TCPCI_MSG_SOP, dpm[port].vdm_attention,
- dpm[port].vdm_cnt) == true)
- /* Trigger PE to start a VDM command run */
- pd_dpm_request(port, DPM_REQUEST_VDM);
-
- /* Clear flag after message is sent to PE layer */
- DPM_CLR_FLAG(port, DPM_FLAG_SEND_ATTENTION);
-}
-
-void dpm_run(int port)
-{
- if (pd_get_data_role(port) == PD_ROLE_DFP) {
- /* Run DFP related DPM requests */
- if (DPM_CHK_FLAG(port, DPM_FLAG_EXIT_REQUEST))
- dpm_attempt_mode_exit(port);
- else if (!DPM_CHK_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE))
- dpm_attempt_mode_entry(port);
- } else {
- /* Run UFP related DPM requests */
- if (DPM_CHK_FLAG(port, DPM_FLAG_SEND_ATTENTION))
- dpm_send_attention_vdm(port);
- }
-}
-
-/*
- * Source-out policy variables and APIs
- *
- * Priority for the available 3.0 A ports is given in the following order:
- * - sink partners which report requiring > 1.5 A in their Sink_Capabilities
- */
-
-/*
- * Bitmasks of port numbers in each following category
- *
- * Note: request bitmasks should be accessed atomically as other ports may alter
- * them
- */
-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;
-/* Ports with FRS source needing > 1.5 A */
-static uint32_t source_frs_max_requested;
-/* Ports with non-PD sinks, so current requirements are unknown */
-static uint32_t non_pd_sink_max_requested;
-
-#define LOWEST_PORT(p) __builtin_ctz(p) /* Undefined behavior if p == 0 */
-
-static int count_port_bits(uint32_t bitmask)
-{
- int i, total = 0;
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- if (bitmask & BIT(i))
- total++;
- }
-
- return total;
-}
-
-/*
- * Centralized, mutex-controlled updates to the claimed 3.0 A ports
- */
-static void balance_source_ports(void);
-DECLARE_DEFERRED(balance_source_ports);
-
-static void balance_source_ports(void)
-{
- uint32_t removed_ports, new_ports;
- static bool deferred_waiting;
-
- if (task_get_current() == TASK_ID_HOOKS)
- deferred_waiting = false;
-
- /*
- * Ignore balance attempts while we're waiting for a downgraded port to
- * finish the downgrade.
- */
- if (deferred_waiting)
- return;
-
- mutex_lock(&max_current_claimed_lock);
-
- /* Remove any ports which no longer require 3.0 A */
- removed_ports = max_current_claimed & ~(sink_max_pdo_requested |
- source_frs_max_requested |
- non_pd_sink_max_requested);
- max_current_claimed &= ~removed_ports;
-
- /* Allocate 3.0 A to new PD sink ports that need it */
- new_ports = sink_max_pdo_requested & ~max_current_claimed;
- while (new_ports) {
- int new_max_port = LOWEST_PORT(new_ports);
-
- if (count_port_bits(max_current_claimed) <
- CONFIG_USB_PD_3A_PORTS) {
- max_current_claimed |= BIT(new_max_port);
- typec_select_src_current_limit_rp(new_max_port,
- TYPEC_RP_3A0);
- } else if (non_pd_sink_max_requested & max_current_claimed) {
- /* Always downgrade non-PD ports first */
- int rem_non_pd = LOWEST_PORT(non_pd_sink_max_requested &
- max_current_claimed);
- typec_select_src_current_limit_rp(rem_non_pd,
- typec_get_default_current_limit_rp(rem_non_pd));
- max_current_claimed &= ~BIT(rem_non_pd);
-
- /* Wait tSinkAdj before using current */
- deferred_waiting = true;
- hook_call_deferred(&balance_source_ports_data,
- PD_T_SINK_ADJ);
- goto unlock;
- } else if (source_frs_max_requested & max_current_claimed) {
- /* Downgrade lowest FRS port from 3.0 A slot */
- int rem_frs = LOWEST_PORT(source_frs_max_requested &
- max_current_claimed);
- pd_dpm_request(rem_frs, DPM_REQUEST_FRS_DET_DISABLE);
- max_current_claimed &= ~BIT(rem_frs);
-
- /* Give 20 ms for the PD task to process DPM flag */
- deferred_waiting = true;
- hook_call_deferred(&balance_source_ports_data,
- 20 * MSEC);
- goto unlock;
- } else {
- /* No lower priority ports to downgrade */
- goto unlock;
- }
- new_ports &= ~BIT(new_max_port);
- }
-
- /* Allocate 3.0 A to any new FRS ports that need it */
- new_ports = source_frs_max_requested & ~max_current_claimed;
- while (new_ports) {
- int new_frs_port = LOWEST_PORT(new_ports);
-
- if (count_port_bits(max_current_claimed) <
- CONFIG_USB_PD_3A_PORTS) {
- max_current_claimed |= BIT(new_frs_port);
- pd_dpm_request(new_frs_port,
- DPM_REQUEST_FRS_DET_ENABLE);
- } else if (non_pd_sink_max_requested & max_current_claimed) {
- int rem_non_pd = LOWEST_PORT(non_pd_sink_max_requested &
- max_current_claimed);
- typec_select_src_current_limit_rp(rem_non_pd,
- typec_get_default_current_limit_rp(rem_non_pd));
- max_current_claimed &= ~BIT(rem_non_pd);
-
- /* Wait tSinkAdj before using current */
- deferred_waiting = true;
- hook_call_deferred(&balance_source_ports_data,
- PD_T_SINK_ADJ);
- goto unlock;
- } else {
- /* No lower priority ports to downgrade */
- goto unlock;
- }
- new_ports &= ~BIT(new_frs_port);
- }
-
- /* Allocate 3.0 A to any non-PD ports which could need it */
- new_ports = non_pd_sink_max_requested & ~max_current_claimed;
- while (new_ports) {
- int new_max_port = LOWEST_PORT(new_ports);
-
- if (count_port_bits(max_current_claimed) <
- CONFIG_USB_PD_3A_PORTS) {
- max_current_claimed |= BIT(new_max_port);
- typec_select_src_current_limit_rp(new_max_port,
- TYPEC_RP_3A0);
- } else {
- /* No lower priority ports to downgrade */
- goto unlock;
- }
- new_ports &= ~BIT(new_max_port);
- }
-unlock:
- mutex_unlock(&max_current_claimed_lock);
-}
-
-/* Process port's first Sink_Capabilities PDO for port current consideration */
-void dpm_evaluate_sink_fixed_pdo(int port, uint32_t vsafe5v_pdo)
-{
- /* Verify partner supplied valid vSafe5V fixed object first */
- if ((vsafe5v_pdo & PDO_TYPE_MASK) != PDO_TYPE_FIXED)
- return;
-
- if (PDO_FIXED_VOLTAGE(vsafe5v_pdo) != 5000)
- return;
-
- if (pd_get_power_role(port) == PD_ROLE_SOURCE) {
- if (CONFIG_USB_PD_3A_PORTS == 0)
- return;
-
- /* Valid PDO to process, so evaluate whether >1.5A is needed */
- if (PDO_FIXED_CURRENT(vsafe5v_pdo) <= 1500)
- return;
-
- atomic_or(&sink_max_pdo_requested, BIT(port));
- } else {
- int frs_current = vsafe5v_pdo & PDO_FIXED_FRS_CURR_MASK;
-
- if (!IS_ENABLED(CONFIG_USB_PD_FRS))
- return;
-
- /* FRS is only supported in PD 3.0 and higher */
- if (pd_get_rev(port, TCPCI_MSG_SOP) == PD_REV20)
- return;
-
- if ((vsafe5v_pdo & PDO_FIXED_DUAL_ROLE) && frs_current) {
- /* Always enable FRS when 3.0 A is not needed */
- if (frs_current == PDO_FIXED_FRS_CURR_DFLT_USB_POWER ||
- frs_current == PDO_FIXED_FRS_CURR_1A5_AT_5V) {
- pd_dpm_request(port,
- DPM_REQUEST_FRS_DET_ENABLE);
- return;
- }
-
- if (CONFIG_USB_PD_3A_PORTS == 0)
- return;
-
- atomic_or(&source_frs_max_requested, BIT(port));
- } else {
- return;
- }
- }
-
- balance_source_ports();
-}
-
-void dpm_add_non_pd_sink(int port)
-{
- if (CONFIG_USB_PD_3A_PORTS == 0)
- return;
-
- atomic_or(&non_pd_sink_max_requested, BIT(port));
-
- balance_source_ports();
-}
-
-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))
- return;
-
- atomic_clear_bits(&sink_max_pdo_requested, BIT(port));
- atomic_clear_bits(&non_pd_sink_max_requested, BIT(port));
-
- /* Restore selected default Rp on the port */
- typec_select_src_current_limit_rp(port,
- typec_get_default_current_limit_rp(port));
-
- balance_source_ports();
-}
-
-void dpm_remove_source(int port)
-{
- if (CONFIG_USB_PD_3A_PORTS == 0)
- return;
-
- if (!IS_ENABLED(CONFIG_USB_PD_FRS))
- return;
-
- if (!(BIT(port) & source_frs_max_requested))
- return;
-
- atomic_clear_bits(&source_frs_max_requested, BIT(port));
-
- balance_source_ports();
-}
-
-/*
- * Note: all ports receive the 1.5 A source offering until they are found to
- * match a criteria on the 3.0 A priority list (ex. through sink capability
- * probing), at which point they will be offered a new 3.0 A source capability.
- */
-__overridable int dpm_get_source_pdo(const uint32_t **src_pdo, const int port)
-{
- /* Max PDO may not exist on boards which don't offer 3 A */
-#if CONFIG_USB_PD_3A_PORTS > 0
- if (max_current_claimed & BIT(port)) {
- *src_pdo = pd_src_pdo_max;
- return pd_src_pdo_max_cnt;
- }
-#endif
-
- *src_pdo = pd_src_pdo;
- return pd_src_pdo_cnt;
-}
-
-int dpm_get_source_current(const int port)
-{
- if (pd_get_power_role(port) == PD_ROLE_SINK)
- return 0;
-
- if (max_current_claimed & BIT(port))
- return 3000;
- else if (typec_get_default_current_limit_rp(port) == TYPEC_RP_1A5)
- return 1500;
- else
- return 500;
-}
diff --git a/common/usbc/usb_pd_host.c b/common/usbc/usb_pd_host.c
deleted file mode 100644
index 4d0fadeec3..0000000000
--- a/common/usbc/usb_pd_host.c
+++ /dev/null
@@ -1,179 +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.
- *
- * Host commands for TCPMv2 USB PD module
- */
-
-#include <string.h>
-
-#include "console.h"
-#include "ec_commands.h"
-#include "host_command.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
-#include "util.h"
-
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-
-/* Retrieve all discovery results for the given port and transmit type */
-static enum ec_status hc_typec_discovery(struct host_cmd_handler_args *args)
-{
- const struct ec_params_typec_discovery *p = args->params;
- struct ec_response_typec_discovery *r = args->response;
- const struct pd_discovery *disc;
- enum tcpci_msg_type type;
-
- /* Confirm the number of HC VDOs matches our stored VDOs */
- BUILD_ASSERT(sizeof(r->discovery_vdo) == sizeof(union disc_ident_ack));
-
- if (p->port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- if (p->partner_type > TYPEC_PARTNER_SOP_PRIME)
- return EC_RES_INVALID_PARAM;
-
- type = p->partner_type == TYPEC_PARTNER_SOP ?
- TCPCI_MSG_SOP : TCPCI_MSG_SOP_PRIME;
-
- /*
- * Clear out access mask so we can track if tasks have touched data
- * since read started.
- */
- pd_discovery_access_clear(p->port, type);
-
- disc = pd_get_am_discovery_and_notify_access(p->port, type);
-
- /* Initialize return size to that of discovery with no SVIDs */
- args->response_size = sizeof(*r);
-
- if (pd_get_identity_discovery(p->port, type) == PD_DISC_COMPLETE) {
- r->identity_count = disc->identity_cnt;
- memcpy(r->discovery_vdo,
- pd_get_identity_response(p->port, type)->raw_value,
- sizeof(r->discovery_vdo));
- } else {
- r->identity_count = 0;
- return EC_RES_SUCCESS;
- }
-
- if (pd_get_modes_discovery(p->port, type) == PD_DISC_COMPLETE) {
- int svid_i;
- int max_resp_svids = (args->response_max - args->response_size)/
- sizeof(struct svid_mode_info);
-
- if (disc->svid_cnt > max_resp_svids) {
- CPRINTS("Warn: SVIDS exceeded HC response");
- r->svid_count = max_resp_svids;
- } else {
- r->svid_count = disc->svid_cnt;
- }
-
- for (svid_i = 0; svid_i < r->svid_count; svid_i++) {
- r->svids[svid_i].svid = disc->svids[svid_i].svid;
- r->svids[svid_i].mode_count =
- disc->svids[svid_i].mode_cnt;
- memcpy(r->svids[svid_i].mode_vdo,
- disc->svids[svid_i].mode_vdo,
- sizeof(r->svids[svid_i].mode_vdo));
- args->response_size += sizeof(struct svid_mode_info);
- }
- } else {
- r->svid_count = 0;
- }
-
- /*
- * Verify that another task did not access this data during the duration
- * of the copy. If the data was accessed, return BUSY so the AP will
- * try retrieving again and get the updated data.
- */
- if (!pd_discovery_access_validate(p->port, type)) {
- CPRINTS("[C%d] %s returns EC_RES_BUSY!!\n", p->port, __func__);
- return EC_RES_BUSY;
- }
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_TYPEC_DISCOVERY,
- hc_typec_discovery,
- EC_VER_MASK(0));
-
-static enum ec_status hc_typec_control(struct host_cmd_handler_args *args)
-{
- const struct ec_params_typec_control *p = args->params;
-
- if (p->port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- switch (p->command) {
- case TYPEC_CONTROL_COMMAND_EXIT_MODES:
- pd_dpm_request(p->port, DPM_REQUEST_EXIT_MODES);
- break;
- case TYPEC_CONTROL_COMMAND_CLEAR_EVENTS:
- pd_clear_events(p->port, p->clear_events_mask);
- break;
- case TYPEC_CONTROL_COMMAND_ENTER_MODE:
- return pd_request_enter_mode(p->port, p->mode_to_enter);
- default:
- return EC_RES_INVALID_PARAM;
- }
-
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_TYPEC_CONTROL, hc_typec_control, EC_VER_MASK(0));
-
-static enum ec_status hc_typec_status(struct host_cmd_handler_args *args)
-{
- const struct ec_params_typec_status *p = args->params;
- struct ec_response_typec_status *r = args->response;
- const char *tc_state_name;
-
- if (p->port >= board_get_usb_pd_port_count())
- return EC_RES_INVALID_PARAM;
-
- if (args->response_max < sizeof(*r))
- return EC_RES_RESPONSE_TOO_BIG;
-
- args->response_size = sizeof(*r);
-
- r->pd_enabled = pd_comm_is_enabled(p->port);
- r->dev_connected = pd_is_connected(p->port);
- r->sop_connected = pd_capable(p->port);
-
- r->power_role = pd_get_power_role(p->port);
- r->data_role = pd_get_data_role(p->port);
- r->vconn_role = pd_get_vconn_state(p->port) ? PD_ROLE_VCONN_SRC :
- PD_ROLE_VCONN_OFF;
- r->polarity = pd_get_polarity(p->port);
- r->cc_state = pd_get_task_cc_state(p->port);
- r->dp_pin = get_dp_pin_mode(p->port);
- r->mux_state = usb_mux_get(p->port);
-
- tc_state_name = pd_get_task_state_name(p->port);
- strzcpy(r->tc_state, tc_state_name, sizeof(r->tc_state));
-
- r->events = pd_get_events(p->port);
-
- r->sop_revision = r->sop_connected ?
- PD_STATUS_REV_SET_MAJOR(pd_get_rev(p->port, TCPCI_MSG_SOP)) : 0;
- r->sop_prime_revision =
- pd_get_identity_discovery(p->port, TCPCI_MSG_SOP_PRIME) ==
- PD_DISC_COMPLETE ?
- PD_STATUS_REV_SET_MAJOR(pd_get_rev(p->port,
- TCPCI_MSG_SOP_PRIME))
- : 0;
-
- r->source_cap_count = pd_get_src_cap_cnt(p->port);
- memcpy(r->source_cap_pdos, pd_get_src_caps(p->port),
- r->source_cap_count * sizeof(uint32_t));
-
- r->sink_cap_count = pd_get_snk_cap_cnt(p->port);
- memcpy(r->sink_cap_pdos, pd_get_snk_caps(p->port),
- r->sink_cap_count * sizeof(uint32_t));
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_TYPEC_STATUS, hc_typec_status, EC_VER_MASK(0));
diff --git a/common/usbc/usb_pd_timer.c b/common/usbc/usb_pd_timer.c
deleted file mode 100644
index 67a574904f..0000000000
--- a/common/usbc/usb_pd_timer.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/* Copyright 2021 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.
- */
-
-#include "assert.h"
-#include "common.h"
-#include "console.h"
-#include "limits.h"
-#include "system.h"
-#include "usb_pd_timer.h"
-#include "usb_tc_sm.h"
-
-#define MAX_PD_PORTS CONFIG_USB_PD_PORT_MAX_COUNT
-#define MAX_PD_TIMERS PD_TIMER_COUNT
-#define PD_TIMERS_ALL_MASK ((uint32_t)(((uint64_t)1 << PD_TIMER_COUNT) - 1))
-
-#define MAX_EXPIRE (0x7FFFFFFF)
-#define NO_TIMEOUT (-1)
-#define EXPIRE_NOW (0)
-
-#define PD_SET_ACTIVE(p, m) atomic_or(&timer_active[p], (m))
-#define PD_CLR_ACTIVE(p, m) atomic_clear_bits(&timer_active[p], (m))
-#define PD_CHK_ACTIVE(p, m) (timer_active[p] & (m))
-
-#define PD_SET_DISABLED(p, m) atomic_or(&timer_disabled[p], (m))
-#define PD_CLR_DISABLED(p, m) atomic_clear_bits(&timer_disabled[p], (m))
-#define PD_CHK_DISABLED(p, m) (timer_disabled[p] & (m))
-
-static uint32_t timer_active[MAX_PD_PORTS];
-static uint32_t timer_disabled[MAX_PD_PORTS];
-static uint64_t timer_expires[MAX_PD_PORTS][MAX_PD_TIMERS];
-
-/*
- * CONFIG_CMD_PD_TIMER debug variables
- */
-static int count[MAX_PD_PORTS];
-static int max_count[MAX_PD_PORTS];
-
-__maybe_unused static __const_data const char * const pd_timer_names[] = {
- [PE_TIMER_BIST_CONT_MODE] = "PE-BIST_CONT_MODE",
- [PE_TIMER_CHUNKING_NOT_SUPPORTED] = "PE-CHUNKING_NOT_SUPPORTED",
- [PE_TIMER_DISCOVER_IDENTITY] = "PE-DISCOVER_IDENTITY",
- [PE_TIMER_NO_RESPONSE] = "PE-NO_RESPONSE",
- [PE_TIMER_PR_SWAP_WAIT] = "PE-PR_SWAP_WAIT",
- [PE_TIMER_PS_HARD_RESET] = "PE-PS_HARD_RESET",
- [PE_TIMER_PS_SOURCE] = "PE-PS_SOURCE",
- [PE_TIMER_PS_TRANSITION] = "PE-PS_TRANSITION",
- [PE_TIMER_SENDER_RESPONSE] = "PE-SENDER_RESPONSE",
- [PE_TIMER_SINK_REQUEST] = "PE-SINK_REQUEST",
- [PE_TIMER_SOURCE_CAP] = "PE-SOURCE_CAP",
- [PE_TIMER_SRC_TRANSITION] = "PE-SRC_TRANSITION",
- [PE_TIMER_SWAP_SOURCE_START] = "PE-SWAP_SOURCE_START",
- [PE_TIMER_TIMEOUT] = "PE-TIMEOUT",
- [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",
-
- [PR_TIMER_CHUNK_SENDER_REQUEST] = "PR-CHUNK_SENDER_REQUEST",
- [PR_TIMER_CHUNK_SENDER_RESPONSE] = "PR-CHUNK_SENDER_RESPONSE",
- [PR_TIMER_HARD_RESET_COMPLETE] = "PR-HARD_RESET_COMPLETE",
- [PR_TIMER_SINK_TX] = "PR-SINK_TX",
- [PR_TIMER_TCPC_TX_TIMEOUT] = "PR-TCPC_TX_TIMEOUT",
-
- [TC_TIMER_CC_DEBOUNCE] = "TC-CC_DEBOUNCE",
- [TC_TIMER_LOW_POWER_EXIT_TIME] = "TC-LOW_POWER_EXIT_TIME",
- [TC_TIMER_LOW_POWER_TIME] = "TC-LOW_POWER_TIME",
- [TC_TIMER_NEXT_ROLE_SWAP] = "TC-NEXT_ROLE_SWAP",
- [TC_TIMER_PD_DEBOUNCE] = "TC-PD_DEBOUNCE",
- [TC_TIMER_TIMEOUT] = "TC-TIMEOUT",
- [TC_TIMER_TRY_WAIT_DEBOUNCE] = "TC-TRY_WAIT_DEBOUNCE",
- [TC_TIMER_VBUS_DEBOUNCE] = "TC-VBUS_DEBOUNCE",
-};
-
-/*****************************************************************************
- * PD_TIMER private functions
- *
- * The view of timers to the outside world is enabled and disabled. Internally
- * timers that are enabled are in the active and inactive states. An active
- * timer has a valid timeout value that gets checked for expiration and can
- * adjust the task wakeup time. An inactive timer is assumed to have expired
- * already and will always return that it is still expired. This timer state
- * will not adjust the task scheduling timeout value.
- */
-static void pd_timer_inactive(int port, enum pd_task_timer timer)
-{
- uint32_t mask = 1 << timer;
-
- if (PD_CHK_ACTIVE(port, mask)) {
- PD_CLR_ACTIVE(port, mask);
-
- if (IS_ENABLED(CONFIG_CMD_PD_TIMER))
- count[port]--;
- }
- PD_CLR_DISABLED(port, mask);
-}
-
-static bool pd_timer_is_active(int port, enum pd_task_timer timer)
-{
- uint32_t mask = 1 << timer;
-
- return PD_CHK_ACTIVE(port, mask);
-}
-
-static bool pd_timer_is_inactive(int port, enum pd_task_timer timer)
-{
- uint32_t mask = 1 << timer;
-
- return !PD_CHK_ACTIVE(port, mask) && !PD_CHK_DISABLED(port, mask);
-}
-
-/*****************************************************************************
- * PD_TIMER public functions
- */
-void pd_timer_init(int port)
-{
- if (IS_ENABLED(CONFIG_CMD_PD_TIMER))
- count[port] = 0;
-
- PD_CLR_ACTIVE(port, PD_TIMERS_ALL_MASK);
- PD_SET_DISABLED(port, PD_TIMERS_ALL_MASK);
-}
-
-void pd_timer_enable(int port, enum pd_task_timer timer, uint32_t expires_us)
-{
- uint32_t mask = 1 << timer;
-
- if (!PD_CHK_ACTIVE(port, mask)) {
- PD_SET_ACTIVE(port, mask);
-
- if (IS_ENABLED(CONFIG_CMD_PD_TIMER)) {
- count[port]++;
- if (count[port] > max_count[port])
- max_count[port] = count[port];
- }
- }
- PD_CLR_DISABLED(port, mask);
- timer_expires[port][timer] = get_time().val + expires_us;
-}
-
-void pd_timer_disable(int port, enum pd_task_timer timer)
-{
- uint32_t mask = 1 << timer;
-
- if (PD_CHK_ACTIVE(port, mask)) {
- PD_CLR_ACTIVE(port, mask);
-
- if (IS_ENABLED(CONFIG_CMD_PD_TIMER))
- count[port]--;
- }
- PD_SET_DISABLED(port, mask);
-}
-
-void pd_timer_disable_range(int port, enum pd_timer_range range)
-{
- int start, end;
- enum pd_task_timer timer;
-
- switch (range) {
- case PE_TIMER_RANGE:
- start = PE_TIMER_START;
- end = PE_TIMER_END;
- break;
- case PR_TIMER_RANGE:
- start = PR_TIMER_START;
- end = PR_TIMER_END;
- break;
- case TC_TIMER_RANGE:
- start = TC_TIMER_START;
- end = TC_TIMER_END;
- break;
- default:
- return;
- }
-
- for (timer = start; timer <= end; ++timer)
- pd_timer_disable(port, timer);
-}
-
-bool pd_timer_is_disabled(int port, enum pd_task_timer timer)
-{
- uint32_t mask = 1 << timer;
-
- return PD_CHK_DISABLED(port, mask);
-}
-
-bool pd_timer_is_expired(int port, enum pd_task_timer timer)
-{
- if (pd_timer_is_active(port, timer)) {
- if (get_time().val >= timer_expires[port][timer]) {
- pd_timer_inactive(port, timer);
- return true;
- }
- return false;
- }
- return pd_timer_is_inactive(port, timer);
-}
-
-void pd_timer_manage_expired(int port)
-{
- int timer;
-
- if (timer_active[port])
- for (timer = 0; timer < MAX_PD_TIMERS; ++timer)
- if (pd_timer_is_active(port, timer) &&
- pd_timer_is_expired(port, timer))
- pd_timer_inactive(port, timer);
-}
-
-int pd_timer_next_expiration(int port)
-{
- int timer;
- int ret_value = MAX_EXPIRE;
- uint64_t now = get_time().val;
-
- for (timer = 0; timer < MAX_PD_TIMERS; ++timer) {
- /* Only use active timers for the next expired value */
- if (pd_timer_is_active(port, timer)) {
- int delta;
- uint64_t t_value = timer_expires[port][timer];
-
- if (t_value <= now) {
- ret_value = EXPIRE_NOW;
- break;
- }
-
- delta = t_value - now;
- if (ret_value > delta)
- ret_value = delta;
- }
- }
-
- if (ret_value == MAX_EXPIRE)
- ret_value = NO_TIMEOUT;
-
- return ret_value;
-}
-
-#ifdef CONFIG_CMD_PD_TIMER
-void pd_timer_dump(int port)
-{
- int timer;
- uint64_t now = get_time().val;
-
- ccprints("Timers(%d): cur=%d max=%d",
- port, count[port], max_count[port]);
-
- for (timer = 0; timer < MAX_PD_TIMERS; ++timer) {
- if (pd_timer_is_disabled(port, timer)) {
- continue;
- } else if (pd_timer_is_active(port, timer)) {
- uint32_t delta = 0;
-
- if (now < timer_expires[port][timer])
- delta = timer_expires[port][timer] - now;
-
- ccprints("[%2d] Active: %s (%d%s)",
- timer, pd_timer_names[timer], (uint32_t)delta,
- tc_event_loop_is_paused(port)
- ? "-PAUSED"
- : "");
- } else {
- ccprints("[%2d] Inactive: %s",
- timer, pd_timer_names[timer]);
- }
- }
-}
-#endif /* CONFIG_CMD_PD_TIMER */
diff --git a/common/usbc/usb_pe_ctvpd_sm.c b/common/usbc/usb_pe_ctvpd_sm.c
deleted file mode 100644
index 346a57a461..0000000000
--- a/common/usbc/usb_pe_ctvpd_sm.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/* Copyright 2019 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.
- */
-
-#include "common.h"
-#include "console.h"
-#include "task.h"
-#include "util.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
-#include "usb_pe_sm.h"
-#include "usb_prl_sm.h"
-#include "usb_pd_tcpm.h"
-#include "usb_tc_sm.h"
-#include "usb_emsg.h"
-#include "usb_sm.h"
-
-/* USB Policy Engine Charge-Through VCONN Powered Device module */
-
-/* Policy Engine Flags */
-#define PE_FLAGS_MSG_RECEIVED BIT(0)
-
-/**
- * This is the PE Port object that contains information needed to
- * implement a VCONN and Charge-Through VCONN Powered Device.
- */
-static struct policy_engine {
- /* state machine context */
- struct sm_ctx ctx;
- /* port flags, see PE_FLAGS_* */
- uint32_t flags;
-} pe[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* List of all policy-engine-level states */
-enum usb_pe_state {
- PE_REQUEST,
-};
-
-/* Forward declare the full list of states. This is indexed by usb_pe_states */
-static const struct usb_state pe_states[];
-
-static void set_state_pe(const int port, enum usb_pe_state new_state)
-{
- set_state(port, &pe[port].ctx, &pe_states[new_state]);
-}
-
-static void pe_init(int port)
-{
- const struct sm_ctx cleared = {};
-
- pe[port].flags = 0;
- pe[port].ctx = cleared;
- set_state_pe(port, PE_REQUEST);
-}
-
-bool pe_in_frs_mode(int port)
-{
- /* Will never be in FRS mode */
- return false;
-}
-
-bool pe_in_local_ams(int port)
-{
- /* We never start a local AMS */
- return false;
-}
-
-void pe_run(int port, int evt, int en)
-{
- static enum sm_local_state local_state[CONFIG_USB_PD_PORT_MAX_COUNT];
-
- switch (local_state[port]) {
- case SM_PAUSED:
- if (!en)
- break;
- /* fall through */
- case SM_INIT:
- pe_init(port);
- local_state[port] = SM_RUN;
- /* fall through */
- case SM_RUN:
- if (en)
- run_state(port, &pe[port].ctx);
- else
- local_state[port] = SM_PAUSED;
- break;
- }
-}
-
-void pe_message_received(int port)
-{
- pe[port].flags |= PE_FLAGS_MSG_RECEIVED;
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-/**
- * NOTE:
- * The Charge-Through Vconn Powered Device's Policy Engine is very
- * simple and no implementation is needed for the following functions
- * that might be called by the Protocol Layer.
- */
-
-void pe_hard_reset_sent(int port)
-{
- /* No implementation needed by this policy engine */
-}
-
-void pe_got_hard_reset(int port)
-{
- /* No implementation needed by this policy engine */
-}
-
-void pe_report_error(int port, enum pe_error e, enum tcpci_msg_type type)
-{
- /* No implementation needed by this policy engine */
-}
-
-void pe_report_discard(int port)
-{
- /* No implementation needed by this policy engine */
-}
-
-void pe_got_soft_reset(int port)
-{
- /* No implementation needed by this policy engine */
-}
-
-void pe_message_sent(int port)
-{
- /* No implementation needed by this policy engine */
-}
-
-static void pe_request_run(const int port)
-{
- uint32_t *payload = (uint32_t *)tx_emsg[port].buf;
- uint32_t header = rx_emsg[port].header;
- uint32_t vdo = *(uint32_t *)rx_emsg[port].buf;
-
- if (pe[port].flags & PE_FLAGS_MSG_RECEIVED) {
- pe[port].flags &= ~PE_FLAGS_MSG_RECEIVED;
-
- /*
- * Only support Structured VDM Discovery
- * Identity message
- */
-
- if (PD_HEADER_TYPE(header) != PD_DATA_VENDOR_DEF)
- return;
-
- if (PD_HEADER_CNT(header) == 0)
- return;
-
- if (!PD_VDO_SVDM(vdo))
- return;
-
- if (PD_VDO_CMD(vdo) != CMD_DISCOVER_IDENT)
- return;
-
-#ifdef CONFIG_USB_CTVPD
- /*
- * We have a valid DISCOVER IDENTITY message.
- * Attempt to reset support timer
- */
- tc_reset_support_timer(port);
-#endif
- /* Prepare to send ACK */
-
- /* VDM Header */
- payload[0] = VDO(
- USB_VID_GOOGLE,
- 1, /* Structured VDM */
- VDO_SVDM_VERS(1) |
- VDO_CMDT(CMDT_RSP_ACK) |
- CMD_DISCOVER_IDENT);
-
- /* ID Header VDO */
- payload[1] = VDO_IDH(
- 0, /* Not a USB Host */
- 1, /* Capable of being enumerated as USB Device */
- IDH_PTYPE_VPD,
- 0, /* Modal Operation Not Supported */
- USB_VID_GOOGLE);
-
- /* Cert State VDO */
- payload[2] = 0;
-
- /* Product VDO */
- payload[3] = VDO_PRODUCT(
- CONFIG_USB_PID,
- USB_BCD_DEVICE);
-
- /* VPD VDO */
- payload[4] = VDO_VPD(
- VPD_HW_VERSION,
- VPD_FW_VERSION,
- VPD_MAX_VBUS_20V,
- IS_ENABLED(CONFIG_USB_CTVPD) ? VPD_CT_CURRENT
- : 0,
- IS_ENABLED(CONFIG_USB_CTVPD) ? VPD_VBUS_IMP(
- VPD_VBUS_IMPEDANCE)
- : 0,
- IS_ENABLED(CONFIG_USB_CTVPD) ? VPD_GND_IMP(
- VPD_GND_IMPEDANCE)
- : 0,
- IS_ENABLED(CONFIG_USB_CTVPD) ? VPD_CTS_SUPPORTED
- : VPD_CTS_NOT_SUPPORTED);
-
- /* 20 bytes, 5 data objects */
- tx_emsg[port].len = 20;
-
- /* Set to highest revision supported by both ports. */
- prl_set_rev(port, TCPCI_MSG_SOP_PRIME,
- (PD_HEADER_REV(header) > PD_REV30) ?
- PD_REV30 : PD_HEADER_REV(header));
- /* Send the ACK */
- prl_send_data_msg(port, TCPCI_MSG_SOP_PRIME,
- PD_DATA_VENDOR_DEF);
- }
-}
-
-/* All policy-engine-level states. */
-static const struct usb_state pe_states[] = {
- [PE_REQUEST] = {
- .run = pe_request_run,
- },
-};
-
-#ifdef TEST_BUILD
-const struct test_sm_data test_pe_sm_data[] = {
- {
- .base = pe_states,
- .size = ARRAY_SIZE(pe_states),
- },
-};
-const int test_pe_sm_data_size = ARRAY_SIZE(test_pe_sm_data);
-#endif
diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c
deleted file mode 100644
index 096f689b0a..0000000000
--- a/common/usbc/usb_pe_drp_sm.c
+++ /dev/null
@@ -1,7486 +0,0 @@
-/* Copyright 2019 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.
- */
-
-#include "atomic.h"
-#include "battery.h"
-#include "battery_smart.h"
-#include "charge_manager.h"
-#include "charge_state.h"
-#include "common.h"
-#include "console.h"
-#include "dps.h"
-#include "driver/tcpm/tcpm.h"
-#include "ec_commands.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "stdbool.h"
-#include "system.h"
-#include "task.h"
-#include "tcpm/tcpm.h"
-#include "util.h"
-#include "usb_common.h"
-#include "usb_dp_alt_mode.h"
-#include "usb_mode.h"
-#include "usb_pd_dpm.h"
-#include "usb_pd_policy.h"
-#include "usb_pd.h"
-#include "usb_pd_tcpm.h"
-#include "usb_pd_timer.h"
-#include "usb_pe_sm.h"
-#include "usb_tbt_alt_mode.h"
-#include "usb_prl_sm.h"
-#include "usb_tc_sm.h"
-#include "usb_emsg.h"
-#include "usb_sm.h"
-#include "usbc_ppc.h"
-
-/*
- * USB Policy Engine Sink / Source module
- *
- * Based on Revision 3.0, Version 1.2 of
- * the USB Power Delivery Specification.
- */
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#else
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif
-
-#define CPRINTF_LX(x, format, args...) \
- do { \
- if (pe_debug_level >= x) \
- CPRINTF(format, ## args); \
- } while (0)
-#define CPRINTF_L1(format, args...) CPRINTF_LX(1, format, ## args)
-#define CPRINTF_L2(format, args...) CPRINTF_LX(2, format, ## args)
-#define CPRINTF_L3(format, args...) CPRINTF_LX(3, format, ## args)
-
-#define CPRINTS_LX(x, format, args...) \
- do { \
- if (pe_debug_level >= x) \
- CPRINTS(format, ## args); \
- } while (0)
-#define CPRINTS_L1(format, args...) CPRINTS_LX(1, format, ## args)
-#define CPRINTS_L2(format, args...) CPRINTS_LX(2, format, ## args)
-#define CPRINTS_L3(format, args...) CPRINTS_LX(3, format, ## args)
-
-#define PE_SET_FLAG(port, flag) atomic_or(&pe[port].flags, (flag))
-#define PE_CLR_FLAG(port, flag) atomic_clear_bits(&pe[port].flags, (flag))
-#define PE_CHK_FLAG(port, flag) (pe[port].flags & (flag))
-
-/*
- * These macros SET, CLEAR, and CHECK, a DPM (Device Policy Manager)
- * Request. The Requests are listed in usb_pe_sm.h.
- */
-#define PE_SET_DPM_REQUEST(port, req) atomic_or(&pe[port].dpm_request, (req))
-#define PE_CLR_DPM_REQUEST(port, req) \
- atomic_clear_bits(&pe[port].dpm_request, (req))
-#define PE_CHK_DPM_REQUEST(port, req) (pe[port].dpm_request & (req))
-
-/*
- * Policy Engine Layer Flags
- * These are reproduced in test/usb_pe.h. If they change here, they must change
- * there.
- */
-
-/* At least one successful PD communication packet received from port partner */
-#define PE_FLAGS_PD_CONNECTION BIT(0)
-/* Accept message received from port partner */
-#define PE_FLAGS_ACCEPT BIT(1)
-/* Power Supply Ready message received from port partner */
-#define PE_FLAGS_PS_READY BIT(2)
-/* Protocol Error was determined based on error recovery current state */
-#define PE_FLAGS_PROTOCOL_ERROR BIT(3)
-/* Set if we are in Modal Operation */
-#define PE_FLAGS_MODAL_OPERATION BIT(4)
-/* A message we requested to be sent has been transmitted */
-#define PE_FLAGS_TX_COMPLETE BIT(5)
-/* A message sent by a port partner has been received */
-#define PE_FLAGS_MSG_RECEIVED BIT(6)
-/* A hard reset has been requested but has not been sent, not currently used */
-#define PE_FLAGS_HARD_RESET_PENDING BIT(7)
-/* Port partner sent a Wait message. Wait before we resend our message */
-#define PE_FLAGS_WAIT BIT(8)
-/* An explicit contract is in place with our port partner */
-#define PE_FLAGS_EXPLICIT_CONTRACT BIT(9)
-/* Waiting for Sink Capabailities timed out. Used for retry error handling */
-#define PE_FLAGS_SNK_WAIT_CAP_TIMEOUT BIT(10)
-/* Power Supply voltage/current transition timed out */
-#define PE_FLAGS_PS_TRANSITION_TIMEOUT BIT(11)
-/* Flag to note current Atomic Message Sequence is interruptible */
-#define PE_FLAGS_INTERRUPTIBLE_AMS BIT(12)
-/* Flag to note Power Supply reset has completed */
-#define PE_FLAGS_PS_RESET_COMPLETE BIT(13)
-/* VCONN swap operation has completed */
-#define PE_FLAGS_VCONN_SWAP_COMPLETE BIT(14)
-/* Flag to note no more setup VDMs (discovery, etc.) should be sent */
-#define PE_FLAGS_VDM_SETUP_DONE BIT(15)
-/* Flag to note PR Swap just completed for Startup entry */
-#define PE_FLAGS_PR_SWAP_COMPLETE BIT(16)
-/* Flag to note Port Discovery port partner replied with BUSY */
-#define PE_FLAGS_VDM_REQUEST_BUSY BIT(17)
-/* Flag to note Port Discovery port partner replied with NAK */
-#define PE_FLAGS_VDM_REQUEST_NAKED BIT(18)
-/* Flag to note FRS/PRS context in shared state machine path */
-#define PE_FLAGS_FAST_ROLE_SWAP_PATH BIT(19)
-/* Flag to note if FRS listening is enabled */
-#define PE_FLAGS_FAST_ROLE_SWAP_ENABLED BIT(20)
-/* Flag to note TCPC passed on FRS signal from port partner */
-#define PE_FLAGS_FAST_ROLE_SWAP_SIGNALED BIT(21)
-/* TODO: POLICY decision: Triggers a DR SWAP attempt from UFP to DFP */
-#define PE_FLAGS_DR_SWAP_TO_DFP BIT(22)
-/*
- * TODO: POLICY decision
- * Flag to trigger a message resend after receiving a WAIT from port partner
- */
-#define PE_FLAGS_WAITING_PR_SWAP BIT(23)
-/* FLAG is set when an AMS is initiated locally. ie. AP requested a PR_SWAP */
-#define PE_FLAGS_LOCALLY_INITIATED_AMS BIT(24)
-/* Flag to note the first message sent in PE_SRC_READY and PE_SNK_READY */
-#define PE_FLAGS_FIRST_MSG BIT(25)
-/* Flag to continue a VDM request if it was interrupted */
-#define PE_FLAGS_VDM_REQUEST_CONTINUE BIT(26)
-/* TODO: POLICY decision: Triggers a Vconn SWAP attempt to on */
-#define PE_FLAGS_VCONN_SWAP_TO_ON BIT(27)
-/* FLAG to track that VDM request to port partner timed out */
-#define PE_FLAGS_VDM_REQUEST_TIMEOUT BIT(28)
-/* FLAG to note message was discarded due to incoming message */
-#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)
-
-/* Message flags which should not persist on returning to ready state */
-#define PE_FLAGS_READY_CLR (PE_FLAGS_LOCALLY_INITIATED_AMS \
- | PE_FLAGS_MSG_DISCARDED \
- | PE_FLAGS_VDM_REQUEST_TIMEOUT \
- | PE_FLAGS_INTERRUPTIBLE_AMS)
-
-/*
- * Combination to check whether a reply to a message was received. Our message
- * should have sent (i.e. not been discarded) and a partner message is ready to
- * process.
- *
- * When chunking is disabled (ex. for PD 2.0), these flags will set
- * on the same run cycle. With chunking, received message will take an
- * additional cycle to be flagged.
- */
-#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
-
-/* 6.7.4 Capabilities Counter */
-#define N_CAPS_COUNT 25
-
-/* 6.7.5 Discover Identity Counter */
-/*
- * NOTE: The Protocol Layer tries to send a message 3 time before giving up,
- * so a Discover Identity SOP' message will be sent 3*6 = 18 times (slightly
- * less than spec maximum of 20). This counter applies only to cable plug
- * discovery.
- */
-#define N_DISCOVER_IDENTITY_COUNT 6
-
-/*
- * It is permitted to send SOP' Discover Identity messages before a PD contract
- * is in place. However, this is only beneficial if the cable powers up quickly
- * solely from VCONN. Limit the number of retries without a contract to
- * ensure we attempt some cable discovery after a contract is in place.
- */
-#define N_DISCOVER_IDENTITY_PRECONTRACT_LIMIT 2
-
-/*
- * Once this limit of SOP' Discover Identity messages has been set, downgrade
- * to PD 2.0 in case the cable is non-compliant about GoodCRC-ing higher
- * revisions. This limit should be higher than the precontract limit.
- */
-#define N_DISCOVER_IDENTITY_PD3_0_LIMIT 4
-
-/*
- * tDiscoverIdentity is only defined while an explicit contract is in place, so
- * extend the interval between retries pre-contract.
- */
-#define PE_T_DISCOVER_IDENTITY_NO_CONTRACT (200*MSEC)
-
-/*
- * Only VCONN source can communicate with the cable plug. Hence, try VCONN swap
- * 3 times before giving up.
- *
- * Note: This is not a part of power delivery specification
- */
-#define N_VCONN_SWAP_COUNT 3
-
-/*
- * Counter to track how many times to attempt SRC to SNK PR swaps before giving
- * up.
- *
- * Note: This is not a part of power delivery specification
- */
-#define N_SNK_SRC_PR_SWAP_COUNT 5
-
-/*
- * ChromeOS policy:
- * For PD2.0, We must be DFP before sending Discover Identity message
- * to the port partner. Attempt to DR SWAP from UFP to DFP
- * N_DR_SWAP_ATTEMPT_COUNT times before giving up on sending a
- * Discover Identity message.
- */
-#define N_DR_SWAP_ATTEMPT_COUNT 5
-
-#define TIMER_DISABLED 0xffffffffffffffff /* Unreachable time in future */
-
-/*
- * The time that we allow the port partner to send any messages after an
- * explicit contract is established. 200ms was chosen somewhat arbitrarily as
- * it should be long enough for sources to decide to send a message if they were
- * going to, but not so long that a "low power charger connected" notification
- * would be shown in the chrome OS UI. Setting t0o large a delay can cause
- * problems if the PD discovery time exceeds 1s (tAMETimeout)
- */
-#define SRC_SNK_READY_HOLD_OFF_US (200 * MSEC)
-
-/*
- * Function pointer to a Structured Vendor Defined Message (SVDM) response
- * function defined in the board's usb_pd_policy.c file.
- */
-typedef int (*svdm_rsp_func)(int port, uint32_t *payload);
-
-/* List of all Policy Engine level states */
-enum usb_pe_state {
- /* Super States */
- PE_PRS_FRS_SHARED,
- PE_VDM_SEND_REQUEST,
-
- /* Normal States */
- PE_SRC_STARTUP,
- PE_SRC_DISCOVERY,
- PE_SRC_SEND_CAPABILITIES,
- PE_SRC_NEGOTIATE_CAPABILITY,
- PE_SRC_TRANSITION_SUPPLY,
- PE_SRC_READY,
- PE_SRC_DISABLED,
- PE_SRC_CAPABILITY_RESPONSE,
- PE_SRC_HARD_RESET,
- PE_SRC_HARD_RESET_RECEIVED,
- PE_SRC_TRANSITION_TO_DEFAULT,
- PE_SNK_STARTUP,
- PE_SNK_DISCOVERY,
- PE_SNK_WAIT_FOR_CAPABILITIES,
- PE_SNK_EVALUATE_CAPABILITY,
- PE_SNK_SELECT_CAPABILITY,
- PE_SNK_READY,
- PE_SNK_HARD_RESET,
- PE_SNK_TRANSITION_TO_DEFAULT,
- PE_SNK_GIVE_SINK_CAP,
- PE_SNK_GET_SOURCE_CAP,
- PE_SNK_TRANSITION_SINK,
- PE_SEND_SOFT_RESET,
- PE_SOFT_RESET,
- PE_SEND_NOT_SUPPORTED,
- PE_SRC_PING,
- PE_DRS_EVALUATE_SWAP,
- PE_DRS_CHANGE,
- PE_DRS_SEND_SWAP,
- PE_PRS_SRC_SNK_EVALUATE_SWAP,
- PE_PRS_SRC_SNK_TRANSITION_TO_OFF,
- PE_PRS_SRC_SNK_ASSERT_RD,
- PE_PRS_SRC_SNK_WAIT_SOURCE_ON,
- PE_PRS_SRC_SNK_SEND_SWAP,
- PE_PRS_SNK_SRC_EVALUATE_SWAP,
- PE_PRS_SNK_SRC_TRANSITION_TO_OFF,
- PE_PRS_SNK_SRC_ASSERT_RP,
- PE_PRS_SNK_SRC_SOURCE_ON,
- PE_PRS_SNK_SRC_SEND_SWAP,
- PE_VCS_EVALUATE_SWAP,
- PE_VCS_SEND_SWAP,
- PE_VCS_WAIT_FOR_VCONN_SWAP,
- PE_VCS_TURN_ON_VCONN_SWAP,
- PE_VCS_TURN_OFF_VCONN_SWAP,
- PE_VCS_SEND_PS_RDY_SWAP,
- PE_VCS_CBL_SEND_SOFT_RESET,
- PE_VDM_IDENTITY_REQUEST_CBL,
- PE_INIT_PORT_VDM_IDENTITY_REQUEST,
- PE_INIT_VDM_SVIDS_REQUEST,
- PE_INIT_VDM_MODES_REQUEST,
- PE_VDM_REQUEST_DPM,
- PE_VDM_RESPONSE,
- PE_HANDLE_CUSTOM_VDM_REQUEST,
- PE_WAIT_FOR_ERROR_RECOVERY,
- PE_BIST_TX,
- PE_DEU_SEND_ENTER_USB,
- PE_DR_GET_SINK_CAP,
- PE_DR_SNK_GIVE_SOURCE_CAP,
- PE_DR_SRC_GET_SOURCE_CAP,
-
- /* PD3.0 only states below here*/
- PE_FRS_SNK_SRC_START_AMS,
- PE_GIVE_BATTERY_CAP,
- PE_GIVE_BATTERY_STATUS,
- PE_SEND_ALERT,
- PE_SRC_CHUNK_RECEIVED,
- PE_SNK_CHUNK_RECEIVED,
- PE_VCS_FORCE_VCONN,
-};
-
-/*
- * The result of a previously sent DPM request; used by PE_VDM_SEND_REQUEST to
- * indicate to child states when they need to handle a response.
- */
-enum vdm_response_result {
- /* The parent state is still waiting for a response. */
- VDM_RESULT_WAITING,
- /*
- * The parent state parsed a message, but there is nothing for the child
- * to handle, e.g. BUSY.
- */
- VDM_RESULT_NO_ACTION,
- /* The parent state processed an ACK response. */
- VDM_RESULT_ACK,
- /*
- * The parent state processed a NAK-like response (NAK, Not Supported,
- * or response timeout.
- */
- VDM_RESULT_NAK,
-};
-
-/* Forward declare the full list of states. This is indexed by usb_pe_state */
-static const struct usb_state pe_states[];
-
-/*
- * We will use DEBUG LABELS if we will be able to print (COMMON RUNTIME)
- * and either CONFIG_USB_PD_DEBUG_LEVEL is not defined (no override) or
- * we are overriding and the level is not DISABLED.
- *
- * If we can't print or the CONFIG_USB_PD_DEBUG_LEVEL is defined to be 0
- * then the DEBUG LABELS will be removed from the build.
- */
-#if defined(CONFIG_COMMON_RUNTIME) && \
- (!defined(CONFIG_USB_PD_DEBUG_LEVEL) || \
- (CONFIG_USB_PD_DEBUG_LEVEL > 0))
-#define USB_PD_DEBUG_LABELS
-#endif
-
-/* List of human readable state names for console debugging */
-__maybe_unused static __const_data const char * const pe_state_names[] = {
- /* Super States */
-#ifdef CONFIG_USB_PD_REV30
- [PE_PRS_FRS_SHARED] = "SS:PE_PRS_FRS_SHARED",
-#endif
- [PE_VDM_SEND_REQUEST] = "SS:PE_VDM_Send_Request",
-
- /* Normal States */
- [PE_SRC_STARTUP] = "PE_SRC_Startup",
- [PE_SRC_DISCOVERY] = "PE_SRC_Discovery",
- [PE_SRC_SEND_CAPABILITIES] = "PE_SRC_Send_Capabilities",
- [PE_SRC_NEGOTIATE_CAPABILITY] = "PE_SRC_Negotiate_Capability",
- [PE_SRC_TRANSITION_SUPPLY] = "PE_SRC_Transition_Supply",
- [PE_SRC_READY] = "PE_SRC_Ready",
- [PE_SRC_DISABLED] = "PE_SRC_Disabled",
- [PE_SRC_CAPABILITY_RESPONSE] = "PE_SRC_Capability_Response",
- [PE_SRC_HARD_RESET] = "PE_SRC_Hard_Reset",
- [PE_SRC_HARD_RESET_RECEIVED] = "PE_SRC_Hard_Reset_Received",
- [PE_SRC_TRANSITION_TO_DEFAULT] = "PE_SRC_Transition_to_default",
- [PE_SNK_STARTUP] = "PE_SNK_Startup",
- [PE_SNK_DISCOVERY] = "PE_SNK_Discovery",
- [PE_SNK_WAIT_FOR_CAPABILITIES] = "PE_SNK_Wait_for_Capabilities",
- [PE_SNK_EVALUATE_CAPABILITY] = "PE_SNK_Evaluate_Capability",
- [PE_SNK_SELECT_CAPABILITY] = "PE_SNK_Select_Capability",
- [PE_SNK_READY] = "PE_SNK_Ready",
- [PE_SNK_HARD_RESET] = "PE_SNK_Hard_Reset",
- [PE_SNK_TRANSITION_TO_DEFAULT] = "PE_SNK_Transition_to_default",
- [PE_SNK_GIVE_SINK_CAP] = "PE_SNK_Give_Sink_Cap",
- [PE_SNK_GET_SOURCE_CAP] = "PE_SNK_Get_Source_Cap",
- [PE_SNK_TRANSITION_SINK] = "PE_SNK_Transition_Sink",
- [PE_SEND_SOFT_RESET] = "PE_Send_Soft_Reset",
- [PE_SOFT_RESET] = "PE_Soft_Reset",
- [PE_SEND_NOT_SUPPORTED] = "PE_Send_Not_Supported",
- [PE_SRC_PING] = "PE_SRC_Ping",
- [PE_DRS_EVALUATE_SWAP] = "PE_DRS_Evaluate_Swap",
- [PE_DRS_CHANGE] = "PE_DRS_Change",
- [PE_DRS_SEND_SWAP] = "PE_DRS_Send_Swap",
- [PE_PRS_SRC_SNK_EVALUATE_SWAP] = "PE_PRS_SRC_SNK_Evaluate_Swap",
- [PE_PRS_SRC_SNK_TRANSITION_TO_OFF] = "PE_PRS_SRC_SNK_Transition_To_Off",
- [PE_PRS_SRC_SNK_ASSERT_RD] = "PE_PRS_SRC_SNK_Assert_Rd",
- [PE_PRS_SRC_SNK_WAIT_SOURCE_ON] = "PE_PRS_SRC_SNK_Wait_Source_On",
- [PE_PRS_SRC_SNK_SEND_SWAP] = "PE_PRS_SRC_SNK_Send_Swap",
- [PE_PRS_SNK_SRC_EVALUATE_SWAP] = "PE_PRS_SNK_SRC_Evaluate_Swap",
- [PE_PRS_SNK_SRC_TRANSITION_TO_OFF] = "PE_PRS_SNK_SRC_Transition_To_Off",
- [PE_PRS_SNK_SRC_ASSERT_RP] = "PE_PRS_SNK_SRC_Assert_Rp",
- [PE_PRS_SNK_SRC_SOURCE_ON] = "PE_PRS_SNK_SRC_Source_On",
- [PE_PRS_SNK_SRC_SEND_SWAP] = "PE_PRS_SNK_SRC_Send_Swap",
-#ifdef CONFIG_USBC_VCONN
- [PE_VCS_EVALUATE_SWAP] = "PE_VCS_Evaluate_Swap",
- [PE_VCS_SEND_SWAP] = "PE_VCS_Send_Swap",
- [PE_VCS_WAIT_FOR_VCONN_SWAP] = "PE_VCS_Wait_For_Vconn_Swap",
- [PE_VCS_TURN_ON_VCONN_SWAP] = "PE_VCS_Turn_On_Vconn_Swap",
- [PE_VCS_TURN_OFF_VCONN_SWAP] = "PE_VCS_Turn_Off_Vconn_Swap",
- [PE_VCS_SEND_PS_RDY_SWAP] = "PE_VCS_Send_Ps_Rdy_Swap",
- [PE_VCS_CBL_SEND_SOFT_RESET] = "PE_VCS_CBL_Send_Soft_Reset",
-#endif
- [PE_VDM_IDENTITY_REQUEST_CBL] = "PE_VDM_Identity_Request_Cbl",
- [PE_INIT_PORT_VDM_IDENTITY_REQUEST] =
- "PE_INIT_PORT_VDM_Identity_Request",
- [PE_INIT_VDM_SVIDS_REQUEST] = "PE_INIT_VDM_SVIDs_Request",
- [PE_INIT_VDM_MODES_REQUEST] = "PE_INIT_VDM_Modes_Request",
- [PE_VDM_REQUEST_DPM] = "PE_VDM_Request_DPM",
- [PE_VDM_RESPONSE] = "PE_VDM_Response",
- [PE_HANDLE_CUSTOM_VDM_REQUEST] = "PE_Handle_Custom_Vdm_Request",
- [PE_WAIT_FOR_ERROR_RECOVERY] = "PE_Wait_For_Error_Recovery",
- [PE_BIST_TX] = "PE_Bist_TX",
- [PE_DEU_SEND_ENTER_USB] = "PE_DEU_Send_Enter_USB",
- [PE_DR_GET_SINK_CAP] = "PE_DR_Get_Sink_Cap",
- [PE_DR_SNK_GIVE_SOURCE_CAP] = "PE_DR_SNK_Give_Source_Cap",
- [PE_DR_SRC_GET_SOURCE_CAP] = "PE_DR_SRC_Get_Source_Cap",
-
- /* PD3.0 only states below here*/
-#ifdef CONFIG_USB_PD_REV30
- [PE_FRS_SNK_SRC_START_AMS] = "PE_FRS_SNK_SRC_Start_Ams",
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- [PE_GIVE_BATTERY_CAP] = "PE_Give_Battery_Cap",
- [PE_GIVE_BATTERY_STATUS] = "PE_Give_Battery_Status",
- [PE_SEND_ALERT] = "PE_Send_Alert",
-#else
- [PE_SRC_CHUNK_RECEIVED] = "PE_SRC_Chunk_Received",
- [PE_SNK_CHUNK_RECEIVED] = "PE_SNK_Chunk_Received",
-#endif
-#ifdef CONFIG_USBC_VCONN
- [PE_VCS_FORCE_VCONN] = "PE_VCS_Force_Vconn",
-#endif
-#endif /* CONFIG_USB_PD_REV30 */
-};
-
-#ifndef CONFIG_USBC_VCONN
-GEN_NOT_SUPPORTED(PE_VCS_EVALUATE_SWAP);
-#define PE_VCS_EVALUATE_SWAP PE_VCS_EVALUATE_SWAP_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(PE_VCS_SEND_SWAP);
-#define PE_VCS_SEND_SWAP PE_VCS_SEND_SWAP_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(PE_VCS_WAIT_FOR_VCONN_SWAP);
-#define PE_VCS_WAIT_FOR_VCONN_SWAP PE_VCS_WAIT_FOR_VCONN_SWAP_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(PE_VCS_TURN_ON_VCONN_SWAP);
-#define PE_VCS_TURN_ON_VCONN_SWAP PE_VCS_TURN_ON_VCONN_SWAP_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(PE_VCS_TURN_OFF_VCONN_SWAP);
-#define PE_VCS_TURN_OFF_VCONN_SWAP PE_VCS_TURN_OFF_VCONN_SWAP_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(PE_VCS_SEND_PS_RDY_SWAP);
-#define PE_VCS_SEND_PS_RDY_SWAP PE_VCS_SEND_PS_RDY_SWAP_NOT_SUPPORTED
-#endif /* CONFIG_USBC_VCONN */
-
-#ifndef CONFIG_USB_PD_REV30
-GEN_NOT_SUPPORTED(PE_FRS_SNK_SRC_START_AMS);
-#define PE_FRS_SNK_SRC_START_AMS PE_FRS_SNK_SRC_START_AMS_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(PE_PRS_FRS_SHARED);
-#define PE_PRS_FRS_SHARED PE_PRS_FRS_SHARED_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(PE_SRC_CHUNK_RECEIVED);
-#define PE_SRC_CHUNK_RECEIVED PE_SRC_CHUNK_RECEIVED_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(PE_SNK_CHUNK_RECEIVED);
-#define PE_SNK_CHUNK_RECEIVED PE_SNK_CHUNK_RECEIVED_NOT_SUPPORTED
-#endif /* CONFIG_USB_PD_REV30 */
-
-#if !defined(CONFIG_USBC_VCONN) || !defined(CONFIG_USB_PD_REV30)
-GEN_NOT_SUPPORTED(PE_VCS_FORCE_VCONN);
-#define PE_VCS_FORCE_VCONN PE_VCS_FORCE_VCONN_NOT_SUPPORTED
-#endif
-
-#ifndef CONFIG_USB_PD_EXTENDED_MESSAGES
-GEN_NOT_SUPPORTED(PE_GIVE_BATTERY_CAP);
-#define PE_GIVE_BATTERY_CAP PE_GIVE_BATTERY_CAP_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(PE_GIVE_BATTERY_STATUS);
-#define PE_GIVE_BATTERY_STATUS PE_GIVE_BATTERY_STATUS_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(PE_SEND_ALERT);
-#define PE_SEND_ALERT PE_SEND_ALERT_NOT_SUPPORTED
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
-GEN_NOT_SUPPORTED(PE_SRC_CHUNK_RECEIVED);
-#define PE_SRC_CHUNK_RECEIVED PE_SRC_CHUNK_RECEIVED_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(PE_SNK_CHUNK_RECEIVED);
-#define PE_SNK_CHUNK_RECEIVED PE_SNK_CHUNK_RECEIVED_NOT_SUPPORTED
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-
-static enum sm_local_state local_state[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/*
- * Common message send checking
- *
- * PE_MSG_SEND_PENDING: A message has been requested to be sent. It has
- * not been GoodCRCed or Discarded.
- * PE_MSG_SEND_COMPLETED: The message that was requested has been sent.
- * This will only be returned one time and any other
- * request for message send status will just return
- * PE_MSG_SENT. This message actually includes both
- * The COMPLETED and the SENT bit for easier checking.
- * NOTE: PE_MSG_SEND_COMPLETED will only be returned
- * a single time, directly after TX_COMPLETE.
- * PE_MSG_SENT: The message that was requested to be sent has
- * successfully been transferred to the partner.
- * PE_MSG_DISCARDED: The message that was requested to be sent was
- * discarded. The partner did not receive it.
- * NOTE: PE_MSG_DISCARDED will only be returned
- * one time and it is up to the caller to process
- * what ever is needed to handle the Discard.
- * PE_MSG_DPM_DISCARDED: The message that was requested to be sent was
- * discarded and an active DRP_REQUEST was active.
- * The DRP_REQUEST that was current will be moved
- * back to the drp_requests so it can be performed
- * later if needed.
- * NOTE: PE_MSG_DPM_DISCARDED will only be returned
- * one time and it is up to the caller to process
- * what ever is needed to handle the Discard.
- */
-enum pe_msg_check {
- PE_MSG_SEND_PENDING = BIT(0),
- PE_MSG_SENT = BIT(1),
- PE_MSG_DISCARDED = BIT(2),
-
- PE_MSG_SEND_COMPLETED = BIT(3) | PE_MSG_SENT,
- PE_MSG_DPM_DISCARDED = BIT(4) | PE_MSG_DISCARDED,
-};
-static void pe_sender_response_msg_entry(const int port);
-static enum pe_msg_check pe_sender_response_msg_run(const int port);
-static void pe_sender_response_msg_exit(const int port);
-
-/* Debug log level - higher number == more log */
-#ifdef CONFIG_USB_PD_DEBUG_LEVEL
-static const enum debug_level pe_debug_level = CONFIG_USB_PD_DEBUG_LEVEL;
-#else
-static enum debug_level pe_debug_level = DEBUG_LEVEL_1;
-#endif
-
-/*
- * Policy Engine State Machine Object
- */
-static struct policy_engine {
- /* state machine context */
- struct sm_ctx ctx;
- /* current port power role (SOURCE or SINK) */
- enum pd_power_role power_role;
- /* current port data role (DFP or UFP) */
- enum pd_data_role data_role;
- /* state machine flags */
- uint32_t flags;
- /* Device Policy Manager Request */
- uint32_t dpm_request;
- uint32_t dpm_curr_request;
- /* last requested voltage PDO index */
- int requested_idx;
-
- /*
- * Port events - PD_STATUS_EVENT_* values
- * Set from PD task but may be cleared by host command
- */
- uint32_t events;
-
- /* port address where soft resets are sent */
- enum tcpci_msg_type soft_reset_sop;
-
- /* Current limit / voltage based on the last request message */
- uint32_t curr_limit;
- uint32_t supply_voltage;
-
- /* PD_VDO_INVALID is used when there is an invalid VDO */
- int32_t ama_vdo;
- int32_t vpd_vdo;
- /* Alternate mode discovery results */
- struct pd_discovery discovery[DISCOVERY_TYPE_COUNT];
- /* Active alternate modes */
- struct partner_active_modes partner_amodes[AMODE_TYPE_COUNT];
-
- /* Partner type to send */
- enum tcpci_msg_type tx_type;
-
- /* VDM - used to send information to shared VDM Request state */
- uint32_t vdm_cnt;
- uint32_t vdm_data[VDO_HDR_SIZE + VDO_MAX_SIZE];
- uint8_t vdm_ack_min_data_objects;
-
- /* Counters */
-
- /*
- * This counter is used to retry the Hard Reset whenever there is no
- * response from the remote device.
- */
- uint32_t hard_reset_counter;
-
- /*
- * This counter is used to count the number of Source_Capabilities
- * Messages which have been sent by a Source at power up or after a
- * Hard Reset.
- */
- uint32_t caps_counter;
-
- /*
- * This counter maintains a count of Discover Identity Messages sent
- * to a cable. If no GoodCRC messages are received after
- * nDiscoverIdentityCount, the port shall not send any further
- * SOP'/SOP'' messages.
- */
- uint32_t discover_identity_counter;
- /*
- * For PD2.0, we need to be a DFP before sending a discovery identity
- * message to our port partner. This counter keeps track of how
- * many attempts to DR SWAP from UFP to DFP.
- */
- uint32_t dr_swap_attempt_counter;
-
- /*
- * This counter tracks how many PR Swap messages are sent when the
- * partner responds with a Wait message. Only used during SRC to SNK
- * PR swaps
- */
- uint8_t src_snk_pr_swap_counter;
-
- /*
- * This counter maintains a count of VCONN swap requests. If VCONN swap
- * isn't successful after N_VCONN_SWAP_COUNT, the port calls
- * dpm_vdm_naked().
- */
- uint8_t vconn_swap_counter;
-
- /* Last received source cap */
- uint32_t src_caps[PDO_MAX_OBJECTS];
- int src_cap_cnt; /* -1 on error retrieving source caps */
-
- /* Last received sink cap */
- uint32_t snk_caps[PDO_MAX_OBJECTS];
- int snk_cap_cnt;
-
- /* Attached ChromeOS device id, RW hash, and current RO / RW image */
- uint16_t dev_id;
- uint32_t dev_rw_hash[PD_RW_HASH_SIZE/4];
- enum ec_image current_image;
-} pe[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-test_export_static enum usb_pe_state get_state_pe(const int port);
-test_export_static void set_state_pe(const int port,
- const enum usb_pe_state new_state);
-static void pe_set_dpm_curr_request(const int port, const int request);
-/*
- * The spec. revision is used to index into this array.
- * PD 1.0 (VDO 1.0) - return VDM_VER10
- * PD 2.0 (VDO 1.0) - return VDM_VER10
- * PD 3.0 (VDO 2.0) - return VDM_VER20
- */
-static const uint8_t vdo_ver[] = {
- [PD_REV10] = VDM_VER10,
- [PD_REV20] = VDM_VER10,
- [PD_REV30] = VDM_VER20,
-};
-
-int pd_get_rev(int port, enum tcpci_msg_type type)
-{
- return prl_get_rev(port, type);
-}
-
-int pd_get_vdo_ver(int port, enum tcpci_msg_type type)
-{
- enum pd_rev_type rev = prl_get_rev(port, type);
-
- if (rev < PD_REV30)
- return vdo_ver[rev];
- else
- return VDM_VER20;
-}
-
-static void pe_set_ready_state(int port)
-{
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_READY);
- else
- set_state_pe(port, PE_SNK_READY);
-}
-
-static inline void send_data_msg(int port, enum tcpci_msg_type type,
- enum pd_data_msg_type msg)
-{
- /* Clear any previous TX status before sending a new message */
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- prl_send_data_msg(port, type, msg);
-}
-
-static __maybe_unused inline void send_ext_data_msg(
- int port, enum tcpci_msg_type type, enum pd_ext_msg_type msg)
-{
- /* Clear any previous TX status before sending a new message */
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- prl_send_ext_data_msg(port, type, msg);
-}
-
-static inline void send_ctrl_msg(int port, enum tcpci_msg_type type,
- enum pd_ctrl_msg_type msg)
-{
- /* Clear any previous TX status before sending a new message */
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- prl_send_ctrl_msg(port, type, msg);
-}
-
-static void set_cable_rev(int port)
-{
- /*
- * If port partner runs PD 2.0, cable communication must
- * also be PD 2.0
- */
- if (prl_get_rev(port, TCPCI_MSG_SOP) == PD_REV20) {
- /*
- * If the cable supports PD 3.0, but the port partner supports PD 2.0,
- * redo the cable discover with PD 2.0
- */
- if (prl_get_rev(port, TCPCI_MSG_SOP_PRIME) == PD_REV30 &&
- pd_get_identity_discovery(port, TCPCI_MSG_SOP_PRIME) ==
- PD_DISC_COMPLETE) {
- pd_set_identity_discovery(port, TCPCI_MSG_SOP_PRIME,
- PD_DISC_NEEDED);
- }
- prl_set_rev(port, TCPCI_MSG_SOP_PRIME, PD_REV20);
- }
-}
-
-/* Compile-time insurance to ensure this code does not call into prl directly */
-#define prl_send_data_msg DO_NOT_USE
-#define prl_send_ext_data_msg DO_NOT_USE
-#define prl_send_ctrl_msg DO_NOT_USE
-
-static void pe_init(int port)
-{
- pe[port].flags = 0;
- pe[port].dpm_request = 0;
- pe[port].dpm_curr_request = 0;
- pd_timer_disable_range(port, PE_TIMER_RANGE);
- pe[port].data_role = pd_get_data_role(port);
- pe[port].tx_type = TCPCI_MSG_INVALID;
- pe[port].events = 0;
-
- tc_pd_connection(port, 0);
-
- if (pd_get_power_role(port) == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_STARTUP);
- else
- set_state_pe(port, PE_SNK_STARTUP);
-}
-
-int pe_is_running(int port)
-{
- return local_state[port] == SM_RUN;
-}
-
-bool pe_in_frs_mode(int port)
-{
- return PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH);
-}
-
-bool pe_in_local_ams(int port)
-{
- return !!PE_CHK_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS);
-}
-
-void pe_set_debug_level(enum debug_level debug_level)
-{
-#ifndef CONFIG_USB_PD_DEBUG_LEVEL
- pe_debug_level = debug_level;
-#endif
-}
-
-void pe_run(int port, int evt, int en)
-{
- switch (local_state[port]) {
- case SM_PAUSED:
- if (!en)
- break;
- /* fall through */
- case SM_INIT:
- pe_init(port);
- local_state[port] = SM_RUN;
- /* fall through */
- case SM_RUN:
- if (!en) {
- local_state[port] = SM_PAUSED;
- /*
- * While we are paused, exit all states and wait until
- * initialized again.
- */
- set_state(port, &pe[port].ctx, NULL);
- break;
- }
-
- /*
- * 8.3.3.3.8 PE_SNK_Hard_Reset State
- * The Policy Engine Shall transition to the PE_SNK_Hard_Reset
- * state from any state when:
- * - Hard Reset request from Device Policy Manager
- *
- * USB PD specification clearly states that we should go to
- * PE_SNK_Hard_Reset from ANY state (including states in which
- * port is source) when DPM requests that. This can lead to
- * execute Hard Reset path for sink when actually our power
- * role is source. In our implementation we will choose Hard
- * Reset path depending on current power role.
- */
- if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_HARD_RESET_SEND)) {
- pe_set_dpm_curr_request(port, DPM_REQUEST_HARD_RESET_SEND);
- if (pd_get_power_role(port) == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_HARD_RESET);
- else
- set_state_pe(port, PE_SNK_HARD_RESET);
- }
-
- /*
- * Check for Fast Role Swap signal
- * This is not a typical pattern for adding state changes.
- * I added this here because FRS SIGNALED can happen at any
- * state once we are listening for the signal and we want to
- * make sure to handle it immediately.
- */
- if (IS_ENABLED(CONFIG_USB_PD_REV30) &&
- PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_SIGNALED)) {
- PE_CLR_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_SIGNALED);
- set_state_pe(port, PE_FRS_SNK_SRC_START_AMS);
- }
-
- /* Run state machine */
- run_state(port, &pe[port].ctx);
- break;
- }
-}
-
-int pe_is_explicit_contract(int port)
-{
- return PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT);
-}
-
-void pe_message_received(int port)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- PE_SET_FLAG(port, PE_FLAGS_MSG_RECEIVED);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void pe_hard_reset_sent(int port)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- PE_CLR_FLAG(port, PE_FLAGS_HARD_RESET_PENDING);
-}
-
-void pe_got_hard_reset(int port)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- /*
- * Transition from any state to the PE_SRC_Hard_Reset_Received or
- * PE_SNK_Transition_to_default state when:
- * 1) Hard Reset Signaling is detected.
- */
- pe[port].power_role = pd_get_power_role(port);
-
- /* Exit BIST Test mode, in case the TCPC entered it. */
- tcpc_set_bist_test_mode(port, false);
-
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_HARD_RESET_RECEIVED);
- else
- set_state_pe(port, PE_SNK_TRANSITION_TO_DEFAULT);
-}
-
-#ifdef CONFIG_USB_PD_REV30
-/*
- * pd_got_frs_signal
- *
- * Called by the handler that detects the FRS signal in order to
- * switch PE states to complete the FRS that the hardware has
- * started.
- *
- * If the PE is not running, generate an error recovery to turn off
- * Vbus and get the port back into a known state.
- */
-void pd_got_frs_signal(int port)
-{
- if (pe_is_running(port))
- PE_SET_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_SIGNALED);
- else
- pd_set_error_recovery(port);
-
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-#endif /* CONFIG_USB_PD_REV30 */
-
-/*
- * PE_Set_FRS_Enable
- *
- * This function should be called every time an explicit contract
- * is disabled, to disable FRS.
- *
- * Enabling an explicit contract is not enough to enable FRS, it
- * also requires a Sink Capability power requirement from a Source
- * that supports FRS so we can determine if this is something we
- * can handle.
- */
-static void pe_set_frs_enable(int port, int enable)
-{
- int current = PE_CHK_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_ENABLED);
-
- /* This should only be called from the PD task */
- if (!IS_ENABLED(TEST_BUILD))
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- if (!IS_ENABLED(CONFIG_USB_PD_FRS) || !IS_ENABLED(CONFIG_USB_PD_REV30))
- return;
-
- /* Request an FRS change, only if the state has changed */
- if (!!current == !!enable)
- return;
-
- pd_set_frs_enable(port, enable);
- if (enable) {
- int curr_limit = *pd_get_snk_caps(port)
- & PDO_FIXED_FRS_CURR_MASK;
-
- typec_select_src_current_limit_rp(port,
- curr_limit ==
- PDO_FIXED_FRS_CURR_3A0_AT_5V ?
- TYPEC_RP_3A0 : TYPEC_RP_1A5);
- PE_SET_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_ENABLED);
- } else {
- PE_CLR_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_ENABLED);
- }
-}
-
-void pe_set_explicit_contract(int port)
-{
- PE_SET_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT);
-
- /* Set Rp for collision avoidance */
- if (IS_ENABLED(CONFIG_USB_PD_REV30))
- typec_update_cc(port);
-}
-
-void pe_invalidate_explicit_contract(int port)
-{
- pe_set_frs_enable(port, 0);
-
- PE_CLR_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT);
-
- /* Set Rp for current limit if still attached */
- if (IS_ENABLED(CONFIG_USB_PD_REV30) && pd_is_connected(port))
- typec_update_cc(port);
-}
-
-void pd_notify_event(int port, uint32_t event_mask)
-{
- atomic_or(&pe[port].events, event_mask);
-
- /* Notify the host that new events are available to read */
- pd_send_host_event(PD_EVENT_TYPEC);
-}
-
-void pd_clear_events(int port, uint32_t clear_mask)
-{
- atomic_clear_bits(&pe[port].events, clear_mask);
-}
-
-uint32_t pd_get_events(int port)
-{
- return pe[port].events;
-}
-
-void pe_set_snk_caps(int port, int cnt, uint32_t *snk_caps)
-{
- pe[port].snk_cap_cnt = cnt;
-
- memcpy(pe[port].snk_caps, snk_caps, sizeof(uint32_t) * cnt);
-}
-
-const uint32_t * const pd_get_snk_caps(int port)
-{
- return pe[port].snk_caps;
-}
-
-uint8_t pd_get_snk_cap_cnt(int port)
-{
- return pe[port].snk_cap_cnt;
-}
-
-uint32_t pd_get_requested_voltage(int port)
-{
- return pe[port].supply_voltage;
-}
-
-uint32_t pd_get_requested_current(int port)
-{
- return pe[port].curr_limit;
-}
-
-/*
- * Determine if this port may communicate with the cable plug.
- *
- * In both PD 2.0 and 3.0 (2.5.4 SOP'/SOP'' Communication with Cable Plugs):
- *
- * When no Contract or an Implicit Contract is in place (e.g. after a Power Role
- * Swap or Fast Role Swap) only the Source port that is supplying Vconn is
- * allowed to send packets to a Cable Plug
- *
- * When in an explicit contract, PD 3.0 requires that a port be Vconn source to
- * communicate with the cable. PD 2.0 requires that a port be DFP to
- * communicate with the cable plug, with an implication that it must be Vconn
- * source as well (6.3.11 VCONN_Swap Message).
- */
-static bool pe_can_send_sop_prime(int port)
-{
- if (IS_ENABLED(CONFIG_USBC_VCONN)) {
- if (PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT)) {
- if (prl_get_rev(port, TCPCI_MSG_SOP) == PD_REV20)
- return tc_is_vconn_src(port) &&
- pe[port].data_role == PD_ROLE_DFP;
- else
- return tc_is_vconn_src(port);
- } else {
- return tc_is_vconn_src(port) &&
- pe[port].power_role == PD_ROLE_SOURCE;
- }
- } else {
- return false;
- }
-}
-
-/*
- * Determine if this port may send the given VDM type
- *
- * For PD 2.0, "Only the DFP Shall be an Initrator of Structured VDMs except for
- * the Attention Command that Shall only be initiated by the UFP"
- *
- * For PD 3.0, "Either port May be an Initiator of Structured VDMs except for
- * the Enter Mode and Exit Mode Commands which shall only be initiated by the
- * DFP" (6.4.4.2 Structured VDM)
- *
- * In both revisions, VDMs may only be initiated while in an explicit contract,
- * with the only exception being for cable plug discovery.
- */
-static bool pe_can_send_sop_vdm(int port, int vdm_cmd)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT)) {
- if (prl_get_rev(port, TCPCI_MSG_SOP) == PD_REV20) {
- if (pe[port].data_role == PD_ROLE_UFP &&
- vdm_cmd != CMD_ATTENTION) {
- return false;
- }
- } else {
- if (pe[port].data_role == PD_ROLE_UFP &&
- (vdm_cmd == CMD_ENTER_MODE ||
- vdm_cmd == CMD_EXIT_MODE)) {
- return false;
- }
- }
- return true;
- }
-
- return false;
-}
-
-static void pe_send_soft_reset(const int port, enum tcpci_msg_type type)
-{
- pe[port].soft_reset_sop = type;
- set_state_pe(port, PE_SEND_SOFT_RESET);
-}
-
-void pe_report_discard(int port)
-{
- /*
- * Clear local AMS indicator as our AMS message was discarded, and flag
- * the discard for the PE
- */
- PE_CLR_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS);
- PE_SET_FLAG(port, PE_FLAGS_MSG_DISCARDED);
-
- /* TODO(b/157228506): Ensure all states are checking discard */
-}
-
-/*
- * Utility function to check for an outgoing message discard during states which
- * send a message as a part of an AMS and wait for the transmit to complete.
- * Note these states should not be power transitioning.
- *
- * In these states, discard due to an incoming message is a protocol error.
- */
-static bool pe_check_outgoing_discard(int port)
-{
- /*
- * On outgoing discard, soft reset with SOP* of incoming message
- *
- * See Table 6-65 Response to an incoming Message (except VDM) in PD 3.0
- * Version 2.0 Specification.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED) &&
- PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- enum tcpci_msg_type sop =
- PD_HEADER_GET_SOP(rx_emsg[port].header);
-
- PE_CLR_FLAG(port, PE_FLAGS_MSG_DISCARDED);
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- pe_send_soft_reset(port, sop);
- return true;
- }
-
- return false;
-}
-
-void pe_report_error(int port, enum pe_error e, enum tcpci_msg_type type)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- /*
- * If there is a timeout error while waiting for a chunk of a chunked
- * message, there is no requirement to trigger a soft reset.
- */
- if (e == ERR_RCH_CHUNK_WAIT_TIMEOUT)
- return;
-
- /*
- * Generate Hard Reset if Protocol Error occurred
- * while in PE_Send_Soft_Reset state.
- */
- if (get_state_pe(port) == PE_SEND_SOFT_RESET) {
- if (pe[port].power_role == PD_ROLE_SINK)
- set_state_pe(port, PE_SNK_HARD_RESET);
- else
- set_state_pe(port, PE_SRC_HARD_RESET);
- return;
- }
-
- /*
- * The following states require custom handling of protocol errors,
- * because they either need special handling of the no GoodCRC case
- * (cable identity request, send capabilities), occur before explicit
- * contract (discovery), or happen during a power transition.
- *
- * TODO(b/150774779): TCPMv2: Improve pe_error documentation
- */
- if ((get_state_pe(port) == PE_SRC_SEND_CAPABILITIES ||
- get_state_pe(port) == PE_SRC_TRANSITION_SUPPLY ||
- get_state_pe(port) == PE_PRS_SNK_SRC_EVALUATE_SWAP ||
- get_state_pe(port) == PE_PRS_SNK_SRC_SOURCE_ON ||
- get_state_pe(port) == PE_PRS_SRC_SNK_WAIT_SOURCE_ON ||
- get_state_pe(port) == PE_SRC_DISABLED ||
- 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) ||
- (pe_in_frs_mode(port) &&
- get_state_pe(port) == PE_PRS_SNK_SRC_SEND_SWAP)
- ) {
- PE_SET_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
- task_wake(PD_PORT_TO_TASK_ID(port));
- return;
- }
-
- /*
- * See section 8.3.3.4.1.1 PE_SRC_Send_Soft_Reset State:
- *
- * The PE_Send_Soft_Reset state shall be entered from
- * any state when
- * * A Protocol Error is detected by Protocol Layer during a
- * Non-Interruptible AMS or
- * * A message has not been sent after retries or
- * * When not in an explicit contract and
- * * Protocol Errors occurred on SOP during an Interruptible AMS or
- * * Protocol Errors occurred on SOP during any AMS where the first
- * Message in the sequence has not yet been sent i.e. an unexpected
- * Message is received instead of the expected GoodCRC Message
- * response.
- */
- /* All error types besides transmit errors are Protocol Errors. */
- if ((e != ERR_TCH_XMIT &&
- !PE_CHK_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS))
- || e == ERR_TCH_XMIT
- || (!PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT) &&
- type == TCPCI_MSG_SOP)) {
- pe_send_soft_reset(port, type);
- }
- /*
- * Transition to PE_Snk_Ready or PE_Src_Ready by a Protocol
- * Error during an Interruptible AMS.
- */
- else {
- pe_set_ready_state(port);
- }
-}
-
-void pe_got_soft_reset(int port)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- /*
- * The PE_SRC_Soft_Reset state Shall be entered from any state when a
- * Soft_Reset Message is received from the Protocol Layer.
- */
- set_state_pe(port, PE_SOFT_RESET);
-}
-
-__overridable bool pd_can_charge_from_device(int port, const int pdo_cnt,
- const uint32_t *pdos)
-{
- /*
- * Don't attempt to charge from a device we have no SrcCaps from. Or, if
- * drp_state is FORCE_SOURCE then don't attempt a PRS.
- */
- if (pdo_cnt == 0 || pd_get_dual_role(port) == PD_DRP_FORCE_SOURCE)
- return false;
-
- /*
- * Treat device as a dedicated charger (meaning we should charge
- * from it) if:
- * - it does not support power swap, or
- * - it is unconstrained power, or
- * - it presents at least 27 W of available power
- */
-
- /* Unconstrained Power or NOT Dual Role Power we can charge from */
- if (pdos[0] & PDO_FIXED_UNCONSTRAINED ||
- (pdos[0] & PDO_FIXED_DUAL_ROLE) == 0)
- return true;
-
- /* [virtual] allow_list */
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) {
- uint32_t max_ma, max_mv, max_pdo, max_mw, unused;
-
- /*
- * Get max power that the partner offers (not necessarily what
- * this board will request)
- */
- pd_find_pdo_index(pdo_cnt, pdos,
- PD_REV3_MAX_VOLTAGE,
- &max_pdo);
- pd_extract_pdo_power(max_pdo, &max_ma, &max_mv, &unused);
- max_mw = max_ma * max_mv / 1000;
-
- if (max_mw >= PD_DRP_CHARGE_POWER_MIN)
- return true;
- }
- return false;
-}
-
-void pd_resume_check_pr_swap_needed(int port)
-{
- /*
- * Explicit contract, current power role of SNK, the device
- * indicates it should not power us, and device isn't selected
- * as the charging port (ex. through the GUI) then trigger a PR_Swap
- */
- if (pe_is_explicit_contract(port) &&
- pd_get_power_role(port) == PD_ROLE_SINK &&
- !pd_can_charge_from_device(port, pd_get_src_cap_cnt(port),
- pd_get_src_caps(port)) &&
- (!IS_ENABLED(CONFIG_CHARGE_MANAGER) ||
- charge_manager_get_active_charge_port() != port))
- pd_dpm_request(port, DPM_REQUEST_PR_SWAP);
-}
-
-void pd_dpm_request(int port, enum pd_dpm_request req)
-{
- PE_SET_DPM_REQUEST(port, req);
-}
-
-void pe_vconn_swap_complete(int port)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- PE_SET_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE);
-}
-
-void pe_ps_reset_complete(int port)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- PE_SET_FLAG(port, PE_FLAGS_PS_RESET_COMPLETE);
-}
-
-void pe_message_sent(int port)
-{
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- PE_SET_FLAG(port, PE_FLAGS_TX_COMPLETE);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data,
- int count)
-{
- /* Copy VDM Header */
- pe[port].vdm_data[0] =
- VDO(vid, ((vid & USB_SID_PD) == USB_SID_PD) ? 1 :
- (PD_VDO_CMD(cmd) <= CMD_ATTENTION),
- VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP)) |
- cmd);
-
- /*
- * Copy VDOs after the VDM Header. Note that the count refers to VDO
- * count.
- */
- memcpy((pe[port].vdm_data + 1), data, count * sizeof(uint32_t));
-
- pe[port].vdm_cnt = count + 1;
-
- /*
- * The PE transmit routine assumes that tx_type was set already. Note,
- * that this function is likely called from outside the PD task.
- * (b/180465870)
- */
- pe[port].tx_type = TCPCI_MSG_SOP;
- pd_dpm_request(port, DPM_REQUEST_VDM);
-
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-#ifdef TEST_BUILD
-/*
- * Allow unit tests to access this function to clear internal state data between
- * runs
- */
-void pe_clear_port_data(int port)
-#else
-static void pe_clear_port_data(int port)
-#endif /* TEST_BUILD */
-{
- /*
- * PD 3.0 Section 8.3.3.3.8
- * Note: The HardResetCounter is reset on a power cycle or Detach.
- */
- pe[port].hard_reset_counter = 0;
-
- /* Reset port events */
- pd_clear_events(port, GENMASK(31, 0));
-
- /* But then set disconnected event */
- pd_notify_event(port, PD_STATUS_EVENT_DISCONNECTED);
-
- /* Tell Policy Engine to invalidate the explicit contract */
- pe_invalidate_explicit_contract(port);
-
- /*
- * Saved Source and Sink Capabilities are no longer valid on disconnect
- */
- pd_set_src_caps(port, 0, NULL);
- pe_set_snk_caps(port, 0, NULL);
-
- dpm_remove_sink(port);
- dpm_remove_source(port);
-
- /* Exit BIST Test mode, in case the TCPC entered it. */
- tcpc_set_bist_test_mode(port, false);
-}
-
-static void pe_handle_detach(void)
-{
- const int port = TASK_ID_TO_PD_PORT(task_get_current());
-
- pe_clear_port_data(port);
-}
-DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, pe_handle_detach, HOOK_PRIO_DEFAULT);
-
-#ifdef CONFIG_USB_PD_RESET_MIN_BATT_SOC
-static void pe_update_waiting_batt_flag(void)
-{
- int i;
- int batt_soc = usb_get_battery_soc();
-
- if (batt_soc < CONFIG_USB_PD_RESET_MIN_BATT_SOC ||
- battery_get_disconnect_state() != BATTERY_NOT_DISCONNECTED)
- return;
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- if (PE_CHK_FLAG(i, PE_FLAGS_SNK_WAITING_BATT)) {
- /*
- * Battery has gained sufficient charge to kick off PD
- * negotiation and withstand a hard reset. Clear the
- * flag and perform Hard Reset.
- */
- PE_CLR_FLAG(i, PE_FLAGS_SNK_WAITING_BATT);
- CPRINTS("C%d: Battery has enough charge (%d%%) " \
- "to withstand a hard reset", i, batt_soc);
- pd_dpm_request(i, DPM_REQUEST_HARD_RESET_SEND);
- }
- }
-}
-DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, pe_update_waiting_batt_flag,
- HOOK_PRIO_DEFAULT);
-#endif
-
-/*
- * Private functions
- */
-static void pe_set_dpm_curr_request(const int port,
- const int request)
-{
- PE_CLR_DPM_REQUEST(port, request);
- pe[port].dpm_curr_request = request;
-}
-
-/* Set the TypeC state machine to a new state. */
-test_export_static void set_state_pe(const int port,
- const enum usb_pe_state new_state)
-{
- set_state(port, &pe[port].ctx, &pe_states[new_state]);
-}
-
-/* Get the current TypeC state. */
-test_export_static enum usb_pe_state get_state_pe(const int port)
-{
- return pe[port].ctx.current - &pe_states[0];
-}
-
-/*
- * Handle common DPM requests to both source and sink.
- *
- * Note: it is assumed the calling state set PE_FLAGS_LOCALLY_INITIATED_AMS
- *
- * Returns true if state was set and calling run state should now return.
- */
-static bool common_src_snk_dpm_requests(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES) &&
- PE_CHK_DPM_REQUEST(port, DPM_REQUEST_SEND_ALERT)) {
- pe_set_dpm_curr_request(port, DPM_REQUEST_SEND_ALERT);
- set_state_pe(port, PE_SEND_ALERT);
- return true;
- } else if (IS_ENABLED(CONFIG_USBC_VCONN) &&
- PE_CHK_DPM_REQUEST(port, DPM_REQUEST_VCONN_SWAP)) {
- pe_set_dpm_curr_request(port, DPM_REQUEST_VCONN_SWAP);
- set_state_pe(port, PE_VCS_SEND_SWAP);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_BIST_TX)) {
- pe_set_dpm_curr_request(port, DPM_REQUEST_BIST_TX);
- set_state_pe(port, PE_BIST_TX);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_SNK_STARTUP)) {
- pe_set_dpm_curr_request(port, DPM_REQUEST_SNK_STARTUP);
- set_state_pe(port, PE_SNK_STARTUP);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_SRC_STARTUP)) {
- pe_set_dpm_curr_request(port, DPM_REQUEST_SRC_STARTUP);
- set_state_pe(port, PE_SRC_STARTUP);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_SOFT_RESET_SEND)) {
- pe_set_dpm_curr_request(port, DPM_REQUEST_SOFT_RESET_SEND);
- /* Currently only support sending soft reset to SOP */
- pe_send_soft_reset(port, TCPCI_MSG_SOP);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_PORT_DISCOVERY)) {
- pe_set_dpm_curr_request(port, DPM_REQUEST_PORT_DISCOVERY);
- if (!PE_CHK_FLAG(port, PE_FLAGS_MODAL_OPERATION)) {
- /*
- * Clear counters and reset timer to trigger a
- * port discovery, and also clear any pending VDM send
- * requests.
- */
- pd_dfp_discovery_init(port);
- /*
- * TODO(b/189353401): Do not reinitialize modes when no
- * longer required.
- */
- pd_dfp_mode_init(port);
- pe[port].dr_swap_attempt_counter = 0;
- pe[port].discover_identity_counter = 0;
- pd_timer_enable(port, PE_TIMER_DISCOVER_IDENTITY,
- PD_T_DISCOVER_IDENTITY);
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_VDM);
- }
- return true;
- } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_VDM)) {
- pe_set_dpm_curr_request(port, DPM_REQUEST_VDM);
- /* Send previously set up SVDM. */
- set_state_pe(port, PE_VDM_REQUEST_DPM);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_ENTER_USB)) {
- pe_set_dpm_curr_request(port, DPM_REQUEST_ENTER_USB);
- set_state_pe(port, PE_DEU_SEND_ENTER_USB);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_EXIT_MODES)) {
- pe_set_dpm_curr_request(port, DPM_REQUEST_EXIT_MODES);
- dpm_set_mode_exit_request(port);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_GET_SNK_CAPS)) {
- pe_set_dpm_curr_request(port,
- DPM_REQUEST_GET_SNK_CAPS);
- set_state_pe(port, PE_DR_GET_SINK_CAP);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_SOP_PRIME_SOFT_RESET_SEND)) {
- pe_set_dpm_curr_request(port,
- DPM_REQUEST_SOP_PRIME_SOFT_RESET_SEND);
- pe[port].tx_type = TCPCI_MSG_SOP_PRIME;
- set_state_pe(port, PE_VCS_CBL_SEND_SOFT_RESET);
- return true;
- }
-
- return false;
-}
-
-/*
- * Handle source-specific DPM requests
- *
- * Returns true if state was set and calling run state should now return.
- */
-static bool source_dpm_requests(int port)
-{
- /*
- * Ignore sink-specific request:
- * DPM_REQUEST_NEW_POWER_LEVEL
- * DPM_REQUEST_SOURCE_CAP
- * DPM_REQUEST_FRS_DET_ENABLE
- * DPM_REQURST_FRS_DET_DISABLE
- */
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_NEW_POWER_LEVEL |
- DPM_REQUEST_SOURCE_CAP |
- DPM_REQUEST_FRS_DET_ENABLE |
- DPM_REQUEST_FRS_DET_DISABLE);
-
- if (pe[port].dpm_request) {
- uint32_t dpm_request = pe[port].dpm_request;
-
- PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS);
-
- if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_DR_SWAP)) {
- pe_set_dpm_curr_request(port,
- DPM_REQUEST_DR_SWAP);
- if (PE_CHK_FLAG(port, PE_FLAGS_MODAL_OPERATION))
- set_state_pe(port, PE_SRC_HARD_RESET);
- else
- set_state_pe(port, PE_DRS_SEND_SWAP);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_PR_SWAP)) {
- pe_set_dpm_curr_request(port,
- DPM_REQUEST_PR_SWAP);
- set_state_pe(port, PE_PRS_SRC_SNK_SEND_SWAP);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_GOTO_MIN)) {
- pe_set_dpm_curr_request(port,
- DPM_REQUEST_GOTO_MIN);
- set_state_pe(port, PE_SRC_TRANSITION_SUPPLY);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_SRC_CAP_CHANGE)) {
- pe_set_dpm_curr_request(port,
- DPM_REQUEST_SRC_CAP_CHANGE);
- set_state_pe(port, PE_SRC_SEND_CAPABILITIES);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_GET_SRC_CAPS)) {
- pe_set_dpm_curr_request(port,
- DPM_REQUEST_GET_SRC_CAPS);
- set_state_pe(port, PE_DR_SRC_GET_SOURCE_CAP);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_SEND_PING)) {
- pe_set_dpm_curr_request(port,
- DPM_REQUEST_SEND_PING);
- set_state_pe(port, PE_SRC_PING);
- return true;
- } else if (common_src_snk_dpm_requests(port)) {
- return true;
- }
-
- CPRINTF("Unhandled DPM Request %x received\n",
- dpm_request);
- PE_CLR_DPM_REQUEST(port, dpm_request);
- PE_CLR_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS);
- }
- return false;
-}
-
-/*
- * Handle sink-specific DPM requests
- *
- * Returns true if state was set and calling run state should now return.
- */
-static bool sink_dpm_requests(int port)
-{
- /*
- * Ignore source specific requests:
- * DPM_REQUEST_GOTO_MIN
- * DPM_REQUEST_SRC_CAP_CHANGE,
- * DPM_REQUEST_SEND_PING
- */
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_GOTO_MIN |
- DPM_REQUEST_SRC_CAP_CHANGE |
- DPM_REQUEST_SEND_PING);
-
- if (pe[port].dpm_request) {
- uint32_t dpm_request = pe[port].dpm_request;
-
- PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS);
-
- if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_DR_SWAP)) {
- pe_set_dpm_curr_request(port,
- DPM_REQUEST_DR_SWAP);
- if (PE_CHK_FLAG(port, PE_FLAGS_MODAL_OPERATION))
- set_state_pe(port, PE_SNK_HARD_RESET);
- else
- set_state_pe(port, PE_DRS_SEND_SWAP);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_PR_SWAP)) {
- pe_set_dpm_curr_request(port,
- DPM_REQUEST_PR_SWAP);
- set_state_pe(port, PE_PRS_SNK_SRC_SEND_SWAP);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_SOURCE_CAP)) {
- pe_set_dpm_curr_request(port,
- DPM_REQUEST_SOURCE_CAP);
- set_state_pe(port, PE_SNK_GET_SOURCE_CAP);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_NEW_POWER_LEVEL)) {
- pe_set_dpm_curr_request(port,
- DPM_REQUEST_NEW_POWER_LEVEL);
- set_state_pe(port, PE_SNK_SELECT_CAPABILITY);
- return true;
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_FRS_DET_ENABLE)) {
- pe_set_frs_enable(port, 1);
-
- /* Requires no state change, fall through to false */
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_FRS_DET_ENABLE);
- } else if (PE_CHK_DPM_REQUEST(port,
- DPM_REQUEST_FRS_DET_DISABLE)) {
- pe_set_frs_enable(port, 0);
- /* Restore a default port current limit */
- typec_select_src_current_limit_rp(port,
- CONFIG_USB_PD_PULLUP);
-
- /* Requires no state change, fall through to false */
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_FRS_DET_DISABLE);
- } else if (common_src_snk_dpm_requests(port)) {
- return true;
- } else {
- CPRINTF("Unhandled DPM Request %x received\n",
- dpm_request);
- PE_CLR_DPM_REQUEST(port, dpm_request);
- }
-
- PE_CLR_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS);
- }
- return false;
-}
-
-/* Get the previous TypeC state. */
-static enum usb_pe_state get_last_state_pe(const int port)
-{
- return pe[port].ctx.previous - &pe_states[0];
-}
-
-static void print_current_state(const int port)
-{
- const char *mode = "";
-
- if (IS_ENABLED(CONFIG_USB_PD_REV30) &&
- pe_in_frs_mode(port))
- mode = " FRS-MODE";
-
- if (IS_ENABLED(USB_PD_DEBUG_LABELS))
- CPRINTS_L1("C%d: %s%s", port,
- pe_state_names[get_state_pe(port)], mode);
- else
- CPRINTS("C%d: pe-st%d", port, get_state_pe(port));
-}
-
-static void send_source_cap(int port)
-{
- const uint32_t *src_pdo;
- const int src_pdo_cnt = dpm_get_source_pdo(&src_pdo, port);
-
- if (src_pdo_cnt == 0) {
- /* No source capabilities defined, sink only */
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_REJECT);
- }
-
- tx_emsg[port].len = src_pdo_cnt * 4;
- memcpy(tx_emsg[port].buf, (uint8_t *)src_pdo, tx_emsg[port].len);
-
- send_data_msg(port, TCPCI_MSG_SOP, PD_DATA_SOURCE_CAP);
-}
-
-/*
- * Request desired charge voltage from source.
- */
-static void pe_send_request_msg(int port)
-{
- uint32_t vpd_vdo = 0;
- uint32_t rdo;
- uint32_t curr_limit;
- uint32_t supply_voltage;
-
- /*
- * If we are charging through a VPD, the requested voltage and current
- * might need adjusting.
- */
- if ((get_usb_pd_cable_type(port) == IDH_PTYPE_VPD) &&
- is_vpd_ct_supported(port)) {
- union vpd_vdo vpd = pd_get_am_discovery(port,
- TCPCI_MSG_SOP_PRIME)->identity.product_t1.vpd;
-
- /* The raw vpd_vdo is passed to pd_build_request */
- vpd_vdo = vpd.raw_value;
- }
-
- /* Build and send request RDO */
- pd_build_request(vpd_vdo, &rdo, &curr_limit,
- &supply_voltage, port);
-
- CPRINTF("C%d: Req [%d] %dmV %dmA", port, RDO_POS(rdo),
- supply_voltage, curr_limit);
- if (rdo & RDO_CAP_MISMATCH)
- CPRINTF(" Mismatch");
- CPRINTF("\n");
-
- pe[port].curr_limit = curr_limit;
- pe[port].supply_voltage = supply_voltage;
-
- tx_emsg[port].len = 4;
-
- memcpy(tx_emsg[port].buf, (uint8_t *)&rdo, tx_emsg[port].len);
- send_data_msg(port, TCPCI_MSG_SOP, PD_DATA_REQUEST);
-}
-
-static void pe_update_src_pdo_flags(int port, int pdo_cnt, uint32_t *pdos)
-{
- /*
- * Only parse PDO flags if type is fixed
- *
- * Note: From 6.4.1 Capabilities Message "The vSafe5V Fixed Supply
- * Object Shall always be the first object." so hitting this condition
- * would mean the partner is voilating spec.
- */
- if ((pdos[0] & PDO_TYPE_MASK) != PDO_TYPE_FIXED)
- return;
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) {
- if (pd_can_charge_from_device(port, pdo_cnt, pdos)) {
- charge_manager_update_dualrole(port, CAP_DEDICATED);
- } else {
- charge_manager_update_dualrole(port, CAP_DUALROLE);
- }
- }
-}
-
-/*
- * Evaluate whether our PR role is in the middle of changing, meaning we our
- * current PR role is not the one we expect to have very shortly.
- */
-bool pe_is_pr_swapping(int port)
-{
- enum usb_pe_state cur_state = get_state_pe(port);
-
- if (cur_state == PE_PRS_SRC_SNK_EVALUATE_SWAP ||
- cur_state == PE_PRS_SRC_SNK_TRANSITION_TO_OFF ||
- cur_state == PE_PRS_SNK_SRC_EVALUATE_SWAP ||
- cur_state == PE_PRS_SNK_SRC_TRANSITION_TO_OFF)
- return true;
-
- return false;
-}
-
-void pd_request_power_swap(int port)
-{
- /* Ignore requests when the board does not wish to swap */
- if (!pd_check_power_swap(port))
- return;
-
- /* Ignore requests when our power role is transitioning */
- if (pe_is_pr_swapping(port))
- return;
-
- /*
- * Always reset the SRC to SNK PR swap counter when a PR swap is
- * requested by policy.
- */
- pe[port].src_snk_pr_swap_counter = 0;
- pd_dpm_request(port, DPM_REQUEST_PR_SWAP);
-}
-
-/* The function returns true if there is a PE state change, false otherwise */
-static bool port_try_vconn_swap(int port)
-{
- if (pe[port].vconn_swap_counter < N_VCONN_SWAP_COUNT) {
- pd_dpm_request(port, DPM_REQUEST_VCONN_SWAP);
- set_state_pe(port, get_last_state_pe(port));
- return true;
- }
- return false;
-}
-
-/*
- * Run discovery at our leisure from PE_SNK_Ready or PE_SRC_Ready, after
- * attempting to get into the desired default policy of DFP/Vconn source
- *
- * Return indicates whether set_state was called, in which case the calling
- * function should return as well.
- */
-__maybe_unused static bool pe_attempt_port_discovery(int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- assert(0);
-
- /*
- * DONE set once modal entry is successful, discovery completes, or
- * discovery results in a NAK
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_VDM_SETUP_DONE))
- return false;
-
- /* Apply Port Discovery DR Swap Policy */
- if (port_discovery_dr_swap_policy(port, pe[port].data_role,
- PE_CHK_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP))) {
- PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS);
- PE_CLR_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP);
- set_state_pe(port, PE_DRS_SEND_SWAP);
- return true;
- }
-
- /* Apply Port Discovery VCONN Swap Policy */
- if (IS_ENABLED(CONFIG_USBC_VCONN) &&
- port_discovery_vconn_swap_policy(port,
- PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_TO_ON))) {
- PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS);
- PE_CLR_FLAG(port, PE_FLAGS_VCONN_SWAP_TO_ON);
- set_state_pe(port, PE_VCS_SEND_SWAP);
- return true;
- }
-
- /* If mode entry was successful, disable the timer */
- if (PE_CHK_FLAG(port, PE_FLAGS_VDM_SETUP_DONE)) {
- pd_timer_disable(port, PE_TIMER_DISCOVER_IDENTITY);
- return false;
- }
-
- /*
- * Run discovery functions when the timer indicating either cable
- * discovery spacing or BUSY spacing runs out.
- */
- if (pd_timer_is_expired(port, PE_TIMER_DISCOVER_IDENTITY)) {
- if (pd_get_identity_discovery(port, TCPCI_MSG_SOP_PRIME) ==
- PD_DISC_NEEDED) {
- pe[port].tx_type = TCPCI_MSG_SOP_PRIME;
- set_state_pe(port, PE_VDM_IDENTITY_REQUEST_CBL);
- return true;
- } else if (pd_get_identity_discovery(port, TCPCI_MSG_SOP) ==
- PD_DISC_NEEDED &&
- pe_can_send_sop_vdm(port, CMD_DISCOVER_IDENT)) {
- pe[port].tx_type = TCPCI_MSG_SOP;
- set_state_pe(port,
- PE_INIT_PORT_VDM_IDENTITY_REQUEST);
- return true;
- } else if (pd_get_svids_discovery(port, TCPCI_MSG_SOP) ==
- PD_DISC_NEEDED &&
- pe_can_send_sop_vdm(port, CMD_DISCOVER_SVID)) {
- pe[port].tx_type = TCPCI_MSG_SOP;
- set_state_pe(port, PE_INIT_VDM_SVIDS_REQUEST);
- return true;
- } else if (pd_get_modes_discovery(port, TCPCI_MSG_SOP) ==
- PD_DISC_NEEDED &&
- pe_can_send_sop_vdm(port, CMD_DISCOVER_MODES)) {
- pe[port].tx_type = TCPCI_MSG_SOP;
- set_state_pe(port, PE_INIT_VDM_MODES_REQUEST);
- return true;
- } else if (pd_get_svids_discovery(port, TCPCI_MSG_SOP_PRIME)
- == PD_DISC_NEEDED) {
- pe[port].tx_type = TCPCI_MSG_SOP_PRIME;
- set_state_pe(port, PE_INIT_VDM_SVIDS_REQUEST);
- return true;
- } else if (pd_get_modes_discovery(port, TCPCI_MSG_SOP_PRIME) ==
- PD_DISC_NEEDED) {
- pe[port].tx_type = TCPCI_MSG_SOP_PRIME;
- set_state_pe(port, PE_INIT_VDM_MODES_REQUEST);
- return true;
- }
- }
-
- return false;
-}
-
-bool pd_setup_vdm_request(int port, enum tcpci_msg_type tx_type,
- uint32_t *vdm, uint32_t vdo_cnt)
-{
- if (vdo_cnt < VDO_HDR_SIZE || vdo_cnt > VDO_MAX_SIZE)
- return false;
-
- pe[port].tx_type = tx_type;
- memcpy(pe[port].vdm_data, vdm, vdo_cnt * sizeof(*vdm));
- pe[port].vdm_cnt = vdo_cnt;
-
- return true;
-}
-
-int pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash,
- uint32_t current_image)
-{
- pe[port].dev_id = dev_id;
- memcpy(pe[port].dev_rw_hash, rw_hash, PD_RW_HASH_SIZE);
-#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO
- pd_dev_dump_info(dev_id, rw_hash);
-#endif
- pe[port].current_image = current_image;
-
- if (IS_ENABLED(CONFIG_USB_PD_HOST_CMD)) {
- int i;
-
- /* Search table for matching device / hash */
- for (i = 0; i < RW_HASH_ENTRIES; i++)
- if (dev_id == rw_hash_table[i].dev_id)
- return !memcmp(rw_hash,
- rw_hash_table[i].dev_rw_hash,
- PD_RW_HASH_SIZE);
- }
-
- return 0;
-}
-
-void pd_dev_get_rw_hash(int port, uint16_t *dev_id, uint8_t *rw_hash,
- uint32_t *current_image)
-{
- *dev_id = pe[port].dev_id;
- *current_image = pe[port].current_image;
- if (*dev_id)
- memcpy(rw_hash, pe[port].dev_rw_hash, PD_RW_HASH_SIZE);
-}
-
-/*
- * This function must only be called from the PE_SNK_READY entry and
- * PE_SRC_READY entry State.
- *
- * TODO(b:181339670) Rethink jitter timer restart if this is the first
- * message but the partner gets a message in first, may not want to
- * disable and restart it.
- */
-static void pe_update_wait_and_add_jitter_timer(int port)
-{
- /*
- * In PD2.0 Mode
- *
- * For Source:
- * Give the sink some time to send any messages
- * before we may send messages of our own. Add
- * some jitter of up to ~345ms, to prevent
- * multiple collisions. This delay also allows
- * the sink device to request power role swap
- * and allow the the accept message to be sent
- * prior to CMD_DISCOVER_IDENT being sent in the
- * SRC_READY state.
- *
- * For Sink:
- * Give the source some time to send any messages before
- * we start our interrogation. Add some jitter of up to
- * ~345ms to prevent multiple collisions.
- */
- if (prl_get_rev(port, TCPCI_MSG_SOP) == PD_REV20 &&
- PE_CHK_FLAG(port, PE_FLAGS_FIRST_MSG) &&
- pd_timer_is_disabled(port, PE_TIMER_WAIT_AND_ADD_JITTER)) {
- pd_timer_enable(port, PE_TIMER_WAIT_AND_ADD_JITTER,
- SRC_SNK_READY_HOLD_OFF_US +
- (get_time().le.lo & 0xf) * 23 * MSEC);
- }
-}
-
-/**
- * Common sender response message handling
- *
- * This is setup like a pseudo state machine parent state. It
- * centralizes the SenderResponseTimer for the calling states, as
- * well as checking message send status.
- */
-/*
- * pe_sender_response_msg_entry
- * Initialization for handling sender response messages.
- *
- * @param port USB-C Port number
- */
-static void pe_sender_response_msg_entry(const int port)
-{
- /* Stop sender response timer */
- pd_timer_disable(port, PE_TIMER_SENDER_RESPONSE);
-}
-
-/*
- * pe_sender_response_msg_run
- * Check status of sender response messages.
- *
- * The normal progression of pe_sender_response_msg_entry is:
- * PENDING -> (COMPLETED/SENT) -> SENT -> SENT ...
- * or
- * PENDING -> DISCARDED
- * PENDING -> DPM_DISCARDED
- *
- * NOTE: it is not valid to call this function for a message after
- * receiving either PE_MSG_DISCARDED or PE_MSG_DPM_DISCARDED until
- * another message has been sent and pe_sender_response_msg_entry is called
- * again.
- *
- * @param port USB-C Port number
- * @return the current pe_msg_check
- */
-static enum pe_msg_check pe_sender_response_msg_run(const int port)
-{
- timestamp_t tx_success_ts;
- uint32_t offset;
- if (pd_timer_is_disabled(port, PE_TIMER_SENDER_RESPONSE)) {
- /* Check for Discard */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) {
- int dpm_request = pe[port].dpm_curr_request;
-
- PE_CLR_FLAG(port, PE_FLAGS_MSG_DISCARDED);
- /* Restore the DPM Request */
- if (dpm_request) {
- PE_SET_DPM_REQUEST(port, dpm_request);
- return PE_MSG_DPM_DISCARDED;
- }
- return PE_MSG_DISCARDED;
- }
-
- /* Check for GoodCRC */
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- /* TCPC TX success time stamp */
- tx_success_ts = prl_get_tcpc_tx_success_ts(port);
- /* Calculate the delay from TX success to PE */
- offset = time_since32(tx_success_ts);
-
- /*
- * Initialize and run the SenderResponseTimer by
- * offsetting it with TX transmit success time.
- * This would remove the effect of the latency from
- * propagating the TX status.
- */
- pd_timer_enable(port, PE_TIMER_SENDER_RESPONSE,
- PD_T_SENDER_RESPONSE - offset);
- return PE_MSG_SEND_COMPLETED;
- }
- return PE_MSG_SEND_PENDING;
- }
- return PE_MSG_SENT;
-}
-
-/*
- * pe_sender_response_msg_exit
- * Exit cleanup for handling sender response messages.
- *
- * @param port USB-C Port number
- */
-static void pe_sender_response_msg_exit(int port)
-{
- pd_timer_disable(port, PE_TIMER_SENDER_RESPONSE);
-}
-
-/**
- * PE_SRC_Startup
- */
-static void pe_src_startup_entry(int port)
-{
- print_current_state(port);
-
- /* Reset CapsCounter */
- pe[port].caps_counter = 0;
-
- /* Reset the protocol layer */
- prl_reset_soft(port);
-
- /* Set initial data role */
- pe[port].data_role = pd_get_data_role(port);
-
- /* Set initial power role */
- pe[port].power_role = PD_ROLE_SOURCE;
-
- /* Clear explicit contract. */
- pe_invalidate_explicit_contract(port);
-
- if (PE_CHK_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE);
- /*
- * Protocol layer reset clears the message IDs for all SOP
- * types. Indicate that a SOP' soft reset is required before any
- * other messages are sent to the cable.
- *
- * Note that other paths into this state are for the initial
- * connection and for a hard reset. In both cases the cable
- * should also automatically clear the message IDs so don't
- * generate an SOP' soft reset for those cases. Sending
- * unnecessary SOP' soft resets causes bad behavior with
- * some devices. See b/179325862.
- */
- pd_dpm_request(port, DPM_REQUEST_SOP_PRIME_SOFT_RESET_SEND);
-
- /* Start SwapSourceStartTimer */
- pd_timer_enable(port, PE_TIMER_SWAP_SOURCE_START,
- PD_T_SWAP_SOURCE_START);
-
- /*
- * Evaluate port's sink caps for preferred current, if
- * already available
- */
- if (pd_get_snk_cap_cnt(port) > 0)
- dpm_evaluate_sink_fixed_pdo(port,
- *pd_get_snk_caps(port));
-
- /*
- * Remove prior FRS claims to 3.0 A now that sink current has
- * been claimed, to avoid issues with lower priority ports
- * potentially receiving a 3.0 A claim between calls.
- */
- dpm_remove_source(port);
- } else {
- /*
- * SwapSourceStartTimer delay is not needed, so trigger now.
- * We can't use set_state_pe here, since we need to ensure that
- * the protocol layer is running again (done in run function).
- */
- pd_timer_enable(port, PE_TIMER_SWAP_SOURCE_START, 0);
-
- /*
- * Set DiscoverIdentityTimer to trigger when we enter
- * src_discovery for the first time. After initial startup
- * set, vdm_identity_request_cbl will handle the timer updates.
- */
- pd_timer_enable(port, PE_TIMER_DISCOVER_IDENTITY, 0);
-
- /* Clear port discovery/mode flags */
- pd_dfp_discovery_init(port);
- pd_dfp_mode_init(port);
- pe[port].ama_vdo = PD_VDO_INVALID;
- pe[port].vpd_vdo = PD_VDO_INVALID;
- pe[port].discover_identity_counter = 0;
-
- /* Reset dr swap attempt counter */
- pe[port].dr_swap_attempt_counter = 0;
-
- /* Reset VCONN swap counter */
- pe[port].vconn_swap_counter = 0;
-
- /* Request partner sink caps if a feature requires them */
- if (IS_ENABLED(CONFIG_USB_PD_HOST_CMD) ||
- CONFIG_USB_PD_3A_PORTS > 0 ||
- IS_ENABLED(CONFIG_USB_PD_FRS))
- pd_dpm_request(port, DPM_REQUEST_GET_SNK_CAPS);
- }
-}
-
-static void pe_src_startup_run(int port)
-{
- /* Wait until protocol layer is running */
- if (!prl_is_running(port))
- return;
-
- if (pd_timer_is_expired(port, PE_TIMER_SWAP_SOURCE_START))
- set_state_pe(port, PE_SRC_SEND_CAPABILITIES);
-}
-
-static void pe_src_startup_exit(int port)
-{
- pd_timer_disable(port, PE_TIMER_SWAP_SOURCE_START);
-}
-
-/**
- * PE_SRC_Discovery
- */
-static void pe_src_discovery_entry(int port)
-{
- print_current_state(port);
-
- /*
- * Initialize and run the SourceCapabilityTimer in order
- * to trigger sending a Source_Capabilities Message.
- *
- * The SourceCapabilityTimer Shall continue to run during
- * identity discover and Shall Not be initialized on re-entry
- * to PE_SRC_Discovery.
- *
- * Note: Cable identity is the only valid VDM to probe before a contract
- * is in place. All other probing must happen from ready states.
- */
- if (get_last_state_pe(port) != PE_VDM_IDENTITY_REQUEST_CBL)
- pd_timer_enable(port, PE_TIMER_SOURCE_CAP,
- PD_T_SEND_SOURCE_CAP);
-}
-
-static void pe_src_discovery_run(int port)
-{
- /*
- * Transition to the PE_SRC_Send_Capabilities state when:
- * 1) The SourceCapabilityTimer times out and
- * CapsCounter ≤ nCapsCount.
- *
- * Transition to the PE_SRC_Disabled state when:
- * 1) The Port Partners are not presently PD Connected
- * 2) And the SourceCapabilityTimer times out
- * 3) And CapsCounter > nCapsCount.
- *
- * Transition to the PE_SRC_VDM_Identity_request state when:
- * 1) DPM requests the identity of the cable plug and
- * 2) DiscoverIdentityCounter < nDiscoverIdentityCount
- */
- if (pd_timer_is_expired(port, PE_TIMER_SOURCE_CAP)) {
- if (pe[port].caps_counter <= N_CAPS_COUNT) {
- set_state_pe(port, PE_SRC_SEND_CAPABILITIES);
- return;
- } else if (!PE_CHK_FLAG(port, PE_FLAGS_PD_CONNECTION)) {
- set_state_pe(port, PE_SRC_DISABLED);
- return;
- }
- }
-
- /*
- * Note: While the DiscoverIdentityTimer is only required in an explicit
- * contract, we use it here to ensure we space any potential BUSY
- * requests properly.
- */
- if (pd_get_identity_discovery(port, TCPCI_MSG_SOP_PRIME) ==
- PD_DISC_NEEDED
- && pd_timer_is_expired(port, PE_TIMER_DISCOVER_IDENTITY)
- && pe_can_send_sop_prime(port)
- && (pe[port].discover_identity_counter <
- N_DISCOVER_IDENTITY_PRECONTRACT_LIMIT)) {
- pe[port].tx_type = TCPCI_MSG_SOP_PRIME;
- set_state_pe(port, PE_VDM_IDENTITY_REQUEST_CBL);
- return;
- }
-
- /*
- * Transition to the PE_SRC_Disabled state when:
- * 1) The Port Partners have not been PD Connected.
- * 2) And the NoResponseTimer times out.
- * 3) And the HardResetCounter > nHardResetCount.
- */
- if (!PE_CHK_FLAG(port, PE_FLAGS_PD_CONNECTION) &&
- pd_timer_is_expired(port, PE_TIMER_NO_RESPONSE) &&
- pe[port].hard_reset_counter > N_HARD_RESET_COUNT) {
- set_state_pe(port, PE_SRC_DISABLED);
- return;
- }
-}
-
-/**
- * PE_SRC_Send_Capabilities
- */
-static void pe_src_send_capabilities_entry(int port)
-{
- print_current_state(port);
-
- /* Send PD Capabilities message */
- send_source_cap(port);
- pe_sender_response_msg_entry(port);
-
- /* Increment CapsCounter */
- pe[port].caps_counter++;
-}
-
-static void pe_src_send_capabilities_run(int port)
-{
- enum pe_msg_check msg_check;
-
- /*
- * Check the state of the message sent
- */
- msg_check = pe_sender_response_msg_run(port);
-
- /*
- * Handle Discarded message
- * PE_SNK/SRC_READY if DPM_REQUEST
- * PE_SEND_SOFT_RESET otherwise
- */
- if (msg_check == PE_MSG_DPM_DISCARDED) {
- set_state_pe(port, PE_SRC_READY);
- return;
- } else if (msg_check == PE_MSG_DISCARDED) {
- pe_send_soft_reset(port, TCPCI_MSG_SOP);
- return;
- }
-
- /*
- * Handle message that was just sent
- */
- if (msg_check == PE_MSG_SEND_COMPLETED) {
- /*
- * If a GoodCRC Message is received then the Policy Engine
- * Shall:
- * 1) Stop the NoResponseTimer.
- * 2) Reset the HardResetCounter and CapsCounter to zero.
- * 3) Initialize and run the SenderResponseTimer.
- */
- /* Stop the NoResponseTimer */
- pd_timer_disable(port, PE_TIMER_NO_RESPONSE);
-
- /* Reset the HardResetCounter to zero */
- pe[port].hard_reset_counter = 0;
-
- /* Reset the CapsCounter to zero */
- pe[port].caps_counter = 0;
- }
-
- /*
- * Transition to the PE_SRC_Negotiate_Capability state when:
- * 1) A Request Message is received from the Sink
- */
- if ((msg_check & PE_MSG_SENT) &&
- PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- /*
- * Request Message Received?
- */
- if (PD_HEADER_CNT(rx_emsg[port].header) > 0 &&
- PD_HEADER_TYPE(rx_emsg[port].header) ==
- PD_DATA_REQUEST) {
-
- /*
- * Set to highest revision supported by both
- * ports.
- */
- prl_set_rev(port, TCPCI_MSG_SOP,
- MIN(PD_REVISION, PD_HEADER_REV(rx_emsg[port].header)));
-
- set_cable_rev(port);
-
- /* We are PD connected */
- PE_SET_FLAG(port, PE_FLAGS_PD_CONNECTION);
- tc_pd_connection(port, 1);
-
- /*
- * Handle the Sink Request in
- * PE_SRC_Negotiate_Capability state
- */
- set_state_pe(port, PE_SRC_NEGOTIATE_CAPABILITY);
- return;
- }
-
- /*
- * We have a Protocol Error.
- * PE_SEND_SOFT_RESET
- */
- pe_send_soft_reset(port,
- PD_HEADER_GET_SOP(rx_emsg[port].header));
- return;
- }
-
- /*
- * Transition to the PE_SRC_Discovery state when:
- * 1) The Protocol Layer indicates that the Message has not been sent
- * and we are presently not Connected
- *
- * Send soft reset when:
- * 1) The Protocol Layer indicates that the Message has not been sent
- * and we are already Connected
- *
- * See section 8.3.3.4.1.1 PE_SRC_Send_Soft_Reset State and section
- * 8.3.3.2.3 PE_SRC_Send_Capabilities State.
- *
- * NOTE: The PE_FLAGS_PROTOCOL_ERROR is set if a GoodCRC Message
- * is not received.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
- PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
- if (!PE_CHK_FLAG(port, PE_FLAGS_PD_CONNECTION))
- set_state_pe(port, PE_SRC_DISCOVERY);
- else
- pe_send_soft_reset(port, TCPCI_MSG_SOP);
- return;
- }
-
- /*
- * Transition to the PE_SRC_Disabled state when:
- * 1) The Port Partners have not been PD Connected
- * 2) The NoResponseTimer times out
- * 3) And the HardResetCounter > nHardResetCount.
- *
- * Transition to the Error Recovery state when:
- * 1) The Port Partners have previously been PD Connected
- * 2) The NoResponseTimer times out
- * 3) And the HardResetCounter > nHardResetCount.
- */
- if (pd_timer_is_expired(port, PE_TIMER_NO_RESPONSE)) {
- if (pe[port].hard_reset_counter <= N_HARD_RESET_COUNT)
- set_state_pe(port, PE_SRC_HARD_RESET);
- else if (PE_CHK_FLAG(port, PE_FLAGS_PD_CONNECTION))
- set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY);
- else
- set_state_pe(port, PE_SRC_DISABLED);
- return;
- }
-
- /*
- * Transition to the PE_SRC_Hard_Reset state when:
- * 1) The SenderResponseTimer times out.
- */
- if (pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE)) {
- set_state_pe(port, PE_SRC_HARD_RESET);
- return;
- }
-}
-
-static void pe_src_send_capabilities_exit(int port)
-{
- pe_sender_response_msg_exit(port);
-}
-
-/**
- * PE_SRC_Negotiate_Capability
- */
-static void pe_src_negotiate_capability_entry(int port)
-{
- uint32_t payload;
-
- print_current_state(port);
-
- /* Get message payload */
- payload = *(uint32_t *)(&rx_emsg[port].buf);
-
- /*
- * Evaluate the Request from the Attached Sink
- */
-
- /*
- * Transition to the PE_SRC_Capability_Response state when:
- * 1) The Request cannot be met.
- * 2) Or the Request can be met later from the Power Reserve
- *
- * Transition to the PE_SRC_Transition_Supply state when:
- * 1) The Request can be met
- *
- */
- if (pd_check_requested_voltage(payload, port) != EC_SUCCESS) {
- set_state_pe(port, PE_SRC_CAPABILITY_RESPONSE);
- } else {
- PE_SET_FLAG(port, PE_FLAGS_ACCEPT);
- pe[port].requested_idx = RDO_POS(payload);
- set_state_pe(port, PE_SRC_TRANSITION_SUPPLY);
- }
-}
-
-/**
- * PE_SRC_Transition_Supply
- */
-static void pe_src_transition_supply_entry(int port)
-{
- print_current_state(port);
-
- /* Send a GotoMin Message or otherwise an Accept Message */
- if (PE_CHK_FLAG(port, PE_FLAGS_ACCEPT)) {
- PE_CLR_FLAG(port, PE_FLAGS_ACCEPT);
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_ACCEPT);
- } else {
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_GOTO_MIN);
- }
-}
-
-static void pe_src_transition_supply_run(int port)
-{
- /*
- * Transition to the PE_SRC_Ready state when:
- * 1) The power supply is ready.
- *
- * NOTE: This code block is executed twice:
- * First Pass)
- * When PE_FLAGS_TX_COMPLETE is set due to the
- * PD_CTRL_ACCEPT or PD_CTRL_GOTO_MIN messages
- * being sent.
- *
- * Second Pass)
- * When PE_FLAGS_TX_COMPLETE is set due to the
- * PD_CTRL_PS_RDY message being sent.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- /*
- * NOTE: If a message was received,
- * pe_src_ready state will handle it.
- */
-
- if (PE_CHK_FLAG(port, PE_FLAGS_PS_READY)) {
- PE_CLR_FLAG(port, PE_FLAGS_PS_READY);
-
- /*
- * Set first message flag to trigger a wait and add
- * jitter delay when operating in PD2.0 mode. Skip
- * if we already have a contract.
- */
- if (!pe_is_explicit_contract(port)) {
- PE_SET_FLAG(port, PE_FLAGS_FIRST_MSG);
- pd_timer_disable(port,
- PE_TIMER_WAIT_AND_ADD_JITTER);
- }
-
- /* NOTE: Second pass through this code block */
- /* Explicit Contract is now in place */
- pe_set_explicit_contract(port);
-
- /*
- * Setup to get Device Policy Manager to request
- * Source Capabilities, if needed, for possible
- * PR_Swap. Get the number directly to avoid re-probing
- * if the partner generated an error and left -1 for the
- * count.
- */
- if (pe[port].src_cap_cnt == 0)
- pd_dpm_request(port, DPM_REQUEST_GET_SRC_CAPS);
-
- set_state_pe(port, PE_SRC_READY);
- } else {
- /* NOTE: First pass through this code block */
- /* Wait for tSrcTransition before changing supply. */
- pd_timer_enable(port, PE_TIMER_SRC_TRANSITION,
- PD_T_SRC_TRANSITION);
- }
-
- return;
- }
-
- if (pd_timer_is_expired(port, PE_TIMER_SRC_TRANSITION)) {
- pd_timer_disable(port, PE_TIMER_SRC_TRANSITION);
- /* Transition power supply and send PS_RDY. */
- pd_transition_voltage(pe[port].requested_idx);
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_PS_RDY);
- PE_SET_FLAG(port, PE_FLAGS_PS_READY);
- }
-
- /*
- * Transition to the PE_SRC_Hard_Reset state when:
- * 1) A Protocol Error occurs.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
- PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
- set_state_pe(port, PE_SRC_HARD_RESET);
- }
-}
-
-static void pe_src_transition_supply_exit(int port)
-{
- pd_timer_disable(port, PE_TIMER_SRC_TRANSITION);
-}
-
-/*
- * Transitions state after receiving a Not Supported extended message. Under
- * appropriate conditions, transitions to a PE_{SRC,SNK}_Chunk_Received.
- */
-static void extended_message_not_supported(int port, uint32_t *payload)
-{
- uint16_t ext_header = GET_EXT_HEADER(*payload);
-
- if (IS_ENABLED(CONFIG_USB_PD_REV30) &&
- !IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES) &&
- PD_EXT_HEADER_CHUNKED(ext_header) &&
- PD_EXT_HEADER_DATA_SIZE(ext_header) >
- PD_MAX_EXTENDED_MSG_CHUNK_LEN) {
- set_state_pe(port,
- pe[port].power_role == PD_ROLE_SOURCE ?
- PE_SRC_CHUNK_RECEIVED : PE_SNK_CHUNK_RECEIVED);
- return;
- }
-
- set_state_pe(port, PE_SEND_NOT_SUPPORTED);
-}
-
-/**
- * PE_SRC_Ready
- */
-static void pe_src_ready_entry(int port)
-{
- print_current_state(port);
-
- /* Ensure any message send flags are cleaned up */
- PE_CLR_FLAG(port, PE_FLAGS_READY_CLR);
-
- /* Clear DPM Current Request */
- pe[port].dpm_curr_request = 0;
-
- /*
- * Wait and add jitter if we are operating in PD2.0 mode and no messages
- * have been sent since enter this state.
- */
- pe_update_wait_and_add_jitter_timer(port);
-}
-
-static void pe_src_ready_run(int port)
-{
- /*
- * Handle incoming messages before discovery and DPMs other than hard
- * reset
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- uint8_t type = PD_HEADER_TYPE(rx_emsg[port].header);
- uint8_t cnt = PD_HEADER_CNT(rx_emsg[port].header);
- uint8_t ext = PD_HEADER_EXT(rx_emsg[port].header);
- uint32_t *payload = (uint32_t *)rx_emsg[port].buf;
-
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- /* Extended Message Requests */
- if (ext > 0) {
- switch (type) {
-#if defined(CONFIG_USB_PD_EXTENDED_MESSAGES) && defined(CONFIG_BATTERY)
- case PD_EXT_GET_BATTERY_CAP:
- set_state_pe(port, PE_GIVE_BATTERY_CAP);
- break;
- case PD_EXT_GET_BATTERY_STATUS:
- set_state_pe(port, PE_GIVE_BATTERY_STATUS);
- break;
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES && CONFIG_BATTERY */
- default:
- extended_message_not_supported(port, payload);
- }
- return;
- }
- /* Data Message Requests */
- else if (cnt > 0) {
- switch (type) {
- case PD_DATA_REQUEST:
- set_state_pe(port, PE_SRC_NEGOTIATE_CAPABILITY);
- return;
- case PD_DATA_SINK_CAP:
- break;
- case PD_DATA_VENDOR_DEF:
- if (PD_HEADER_TYPE(rx_emsg[port].header) ==
- PD_DATA_VENDOR_DEF) {
- if (PD_VDO_SVDM(*payload)) {
- set_state_pe(port,
- PE_VDM_RESPONSE);
- } else
- set_state_pe(port,
- PE_HANDLE_CUSTOM_VDM_REQUEST);
- }
- return;
- case PD_DATA_BIST:
- set_state_pe(port, PE_BIST_TX);
- return;
- default:
- set_state_pe(port, PE_SEND_NOT_SUPPORTED);
- return;
- }
- }
- /* Control Message Requests */
- else {
- switch (type) {
- case PD_CTRL_GOOD_CRC:
- break;
- case PD_CTRL_NOT_SUPPORTED:
- break;
- case PD_CTRL_PING:
- break;
- case PD_CTRL_GET_SOURCE_CAP:
- set_state_pe(port, PE_SRC_SEND_CAPABILITIES);
- return;
- case PD_CTRL_GET_SINK_CAP:
- set_state_pe(port, PE_SNK_GIVE_SINK_CAP);
- return;
- case PD_CTRL_GOTO_MIN:
- break;
- case PD_CTRL_PR_SWAP:
- set_state_pe(port,
- PE_PRS_SRC_SNK_EVALUATE_SWAP);
- return;
- case PD_CTRL_DR_SWAP:
- if (PE_CHK_FLAG(port,
- PE_FLAGS_MODAL_OPERATION)) {
- set_state_pe(port, PE_SRC_HARD_RESET);
- return;
- }
-
- set_state_pe(port, PE_DRS_EVALUATE_SWAP);
- return;
- case PD_CTRL_VCONN_SWAP:
- if (IS_ENABLED(CONFIG_USBC_VCONN))
- set_state_pe(port,
- PE_VCS_EVALUATE_SWAP);
- else
- set_state_pe(port,
- PE_SEND_NOT_SUPPORTED);
- return;
- /*
- * USB PD 3.0 6.8.1:
- * Receiving an unexpected message shall be responded
- * to with a soft reset message.
- */
- case PD_CTRL_ACCEPT:
- case PD_CTRL_REJECT:
- case PD_CTRL_WAIT:
- case PD_CTRL_PS_RDY:
- pe_send_soft_reset(port,
- PD_HEADER_GET_SOP(rx_emsg[port].header));
- return;
- /*
- * Receiving an unknown or unsupported message
- * shall be responded to with a not supported message.
- */
- default:
- set_state_pe(port, PE_SEND_NOT_SUPPORTED);
- return;
- }
- }
- }
-
- /*
- * Make sure the PRL layer isn't busy with receiving or transmitting
- * chunked messages before attempting to transmit a new message.
- */
- if (prl_is_busy(port))
- return;
-
- if (PE_CHK_FLAG(port, PE_FLAGS_VDM_REQUEST_CONTINUE)) {
- PE_CLR_FLAG(port, PE_FLAGS_VDM_REQUEST_CONTINUE);
- set_state_pe(port, PE_VDM_REQUEST_DPM);
- return;
- }
-
- if (PE_CHK_FLAG(port, PE_FLAGS_WAITING_PR_SWAP) &&
- pd_timer_is_expired(port, PE_TIMER_PR_SWAP_WAIT)) {
- PE_CLR_FLAG(port, PE_FLAGS_WAITING_PR_SWAP);
- PE_SET_DPM_REQUEST(port, DPM_REQUEST_PR_SWAP);
- }
-
- if (pd_timer_is_disabled(port, PE_TIMER_WAIT_AND_ADD_JITTER) ||
- pd_timer_is_expired(port, PE_TIMER_WAIT_AND_ADD_JITTER)) {
-
- PE_CLR_FLAG(port, PE_FLAGS_FIRST_MSG);
- pd_timer_disable(port, PE_TIMER_WAIT_AND_ADD_JITTER);
-
- /*
- * Handle Device Policy Manager Requests
- */
- if (source_dpm_requests(port))
- return;
-
- /*
- * Attempt discovery if possible, and return if state was
- * changed for that discovery.
- */
- if (pe_attempt_port_discovery(port))
- return;
-
- /* No DPM requests; attempt mode entry/exit if needed */
- dpm_run(port);
- }
-}
-
-/**
- * PE_SRC_Disabled
- */
-static void pe_src_disabled_entry(int port)
-{
- print_current_state(port);
-
- if ((get_usb_pd_cable_type(port) == IDH_PTYPE_VPD) &&
- is_vpd_ct_supported(port)) {
- /*
- * Inform the Device Policy Manager that a Charge-Through VCONN
- * Powered Device was detected.
- */
- tc_ctvpd_detected(port);
- }
-
- if (pd_get_power_role(port) == PD_ROLE_SOURCE)
- dpm_add_non_pd_sink(port);
-
- /*
- * Unresponsive to USB Power Delivery messaging, but not to Hard Reset
- * Signaling. See pe_got_hard_reset
- */
-}
-
-/**
- * PE_SRC_Capability_Response
- */
-static void pe_src_capability_response_entry(int port)
-{
- print_current_state(port);
-
- /* NOTE: Wait messaging should be implemented. */
-
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_REJECT);
-}
-
-static void pe_src_capability_response_run(int port)
-{
- /*
- * Transition to the PE_SRC_Ready state when:
- * 1) There is an Explicit Contract and
- * 2) A Reject Message has been sent and the present Contract is still
- * Valid or
- * 3) A Wait Message has been sent.
- *
- * Transition to the PE_SRC_Hard_Reset state when:
- * 1) There is an Explicit Contract and
- * 2) The Reject Message has been sent and the present
- * Contract is Invalid
- *
- * Transition to the PE_SRC_Wait_New_Capabilities state when:
- * 1) There is no Explicit Contract and
- * 2) A Reject Message has been sent or
- * 3) A Wait Message has been sent.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- if (PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT))
- /*
- * NOTE: The src capabilities listed in
- * board/xxx/usb_pd_policy.c will not
- * change so the present contract will
- * never be invalid.
- */
- set_state_pe(port, PE_SRC_READY);
- else
- /*
- * NOTE: The src capabilities listed in
- * board/xxx/usb_pd_policy.c will not
- * change, so no need to resending them
- * again. Transition to disabled state.
- */
- set_state_pe(port, PE_SRC_DISABLED);
- }
-}
-
-/**
- * PE_SRC_Hard_Reset
- */
-static void pe_src_hard_reset_entry(int port)
-{
- print_current_state(port);
-
- /* Generate Hard Reset Signal */
- prl_execute_hard_reset(port);
-
- /* Increment the HardResetCounter */
- pe[port].hard_reset_counter++;
-
- /* Start NoResponseTimer */
- pd_timer_enable(port, PE_TIMER_NO_RESPONSE, PD_T_NO_RESPONSE);
-
- /* Start PSHardResetTimer */
- pd_timer_enable(port, PE_TIMER_PS_HARD_RESET, PD_T_PS_HARD_RESET);
-
- /* Clear error flags */
- PE_CLR_FLAG(port, PE_FLAGS_VDM_REQUEST_NAKED |
- PE_FLAGS_PROTOCOL_ERROR |
- PE_FLAGS_VDM_REQUEST_BUSY);
-}
-
-static void pe_src_hard_reset_run(int port)
-{
- /*
- * Transition to the PE_SRC_Transition_to_default state when:
- * 1) The PSHardResetTimer times out.
- */
- if (pd_timer_is_expired(port, PE_TIMER_PS_HARD_RESET))
- set_state_pe(port, PE_SRC_TRANSITION_TO_DEFAULT);
-}
-
-static void pe_src_hard_reset_exit(int port)
-{
- pd_timer_disable(port, PE_TIMER_PS_HARD_RESET);
-}
-
-/**
- * PE_SRC_Hard_Reset_Received
- */
-static void pe_src_hard_reset_received_entry(int port)
-{
- print_current_state(port);
-
- /* Start NoResponseTimer */
- pd_timer_enable(port, PE_TIMER_NO_RESPONSE, PD_T_NO_RESPONSE);
-
- /* Start PSHardResetTimer */
- pd_timer_enable(port, PE_TIMER_PS_HARD_RESET, PD_T_PS_HARD_RESET);
-}
-
-static void pe_src_hard_reset_received_run(int port)
-{
- /*
- * Transition to the PE_SRC_Transition_to_default state when:
- * 1) The PSHardResetTimer times out.
- */
- if (pd_timer_is_expired(port, PE_TIMER_PS_HARD_RESET))
- set_state_pe(port, PE_SRC_TRANSITION_TO_DEFAULT);
-}
-
-static void pe_src_hard_reset_received_exit(int port)
-{
- pd_timer_disable(port, PE_TIMER_PS_HARD_RESET);
-}
-
-/**
- * PE_SRC_Transition_To_Default
- */
-static void pe_src_transition_to_default_entry(int port)
-{
- print_current_state(port);
-
- /* Reset flags */
- pe[port].flags = 0;
-
- /* Reset DPM Request */
- pe[port].dpm_request = 0;
-
- /*
- * Request Device Policy Manager to request power
- * supply Hard Resets to vSafe5V via vSafe0V
- * Reset local HW
- * Request Device Policy Manager to set Port Data
- * Role to DFP and turn off VCONN
- */
- tc_hard_reset_request(port);
-}
-
-static void pe_src_transition_to_default_run(int port)
-{
- /*
- * Transition to the PE_SRC_Startup state when:
- * 1) The power supply has reached the default level.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_PS_RESET_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_PS_RESET_COMPLETE);
- /* Inform the Protocol Layer that the Hard Reset is complete */
- prl_hard_reset_complete(port);
- set_state_pe(port, PE_SRC_STARTUP);
- }
-}
-
-/**
- * PE_SNK_Startup State
- */
-static void pe_snk_startup_entry(int port)
-{
- print_current_state(port);
-
- /* Reset the protocol layer */
- prl_reset_soft(port);
-
- /* Set initial data role */
- pe[port].data_role = pd_get_data_role(port);
-
- /* Set initial power role */
- pe[port].power_role = PD_ROLE_SINK;
-
- /* Invalidate explicit contract */
- pe_invalidate_explicit_contract(port);
-
- if (PE_CHK_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE);
- /*
- * Protocol layer reset clears the message IDs for all SOP
- * types. Indicate that a SOP' soft reset is required before any
- * other messages are sent to the cable.
- *
- * Note that other paths into this state are for the initial
- * connection and for a hard reset. In both cases the cable
- * should also automatically clear the message IDs so don't
- * generate an SOP' soft reset for those cases. Sending
- * unnecessary SOP' soft resets causes bad behavior with
- * some devices. See b/179325862.
- */
- pd_dpm_request(port, DPM_REQUEST_SOP_PRIME_SOFT_RESET_SEND);
-
- /*
- * Some port partners may violate spec and attempt to
- * communicate with the cable after power role swaps, despite
- * not being Vconn source. Disable our SOP' receiving here to
- * avoid GoodCRC-ing any erroneous cable probes, and re-enable
- * after our contract is in place.
- */
- if (tc_is_vconn_src(port))
- tcpm_sop_prime_enable(port, false);
-
- dpm_remove_sink(port);
- } else {
- /*
- * Set DiscoverIdentityTimer to trigger when we enter
- * snk_ready for the first time.
- */
- pd_timer_enable(port, PE_TIMER_DISCOVER_IDENTITY, 0);
-
- /* Clear port discovery/mode flags */
- pd_dfp_discovery_init(port);
- pd_dfp_mode_init(port);
- pe[port].discover_identity_counter = 0;
-
- /* Reset dr swap attempt counter */
- pe[port].dr_swap_attempt_counter = 0;
-
- /* Reset VCONN swap counter */
- pe[port].vconn_swap_counter = 0;
- /*
- * TODO: POLICY decision:
- * Mark that we'd like to try being Vconn source and DFP
- */
- PE_SET_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP);
- PE_SET_FLAG(port, PE_FLAGS_VCONN_SWAP_TO_ON);
- }
-
- /*
- * Request sink caps for FRS, output power consideration, or reporting
- * to the AP through host commands.
- *
- * On entry to the PE_SNK_Ready state if the Sink supports Fast Role
- * Swap, then the Policy Engine Shall do the following:
- * - Send a Get_Sink_Cap Message
- */
- if (IS_ENABLED(CONFIG_USB_PD_HOST_CMD) ||
- CONFIG_USB_PD_3A_PORTS > 0 ||
- IS_ENABLED(CONFIG_USB_PD_FRS))
- pd_dpm_request(port, DPM_REQUEST_GET_SNK_CAPS);
-
-}
-
-static void pe_snk_startup_run(int port)
-{
- /* Wait until protocol layer is running */
- if (!prl_is_running(port))
- return;
-
- /*
- * Once the reset process completes, the Policy Engine Shall
- * transition to the PE_SNK_Discovery state
- */
- set_state_pe(port, PE_SNK_DISCOVERY);
-}
-
-/**
- * PE_SNK_Discovery State
- */
-static void pe_snk_discovery_entry(int port)
-{
- print_current_state(port);
-}
-
-static void pe_snk_discovery_run(int port)
-{
- /*
- * Transition to the PE_SNK_Wait_for_Capabilities state when:
- * 1) VBUS has been detected
- */
- if (!pd_check_vbus_level(port, VBUS_REMOVED))
- set_state_pe(port, PE_SNK_WAIT_FOR_CAPABILITIES);
-}
-
-/**
- * PE_SNK_Wait_For_Capabilities State
- */
-static void pe_snk_wait_for_capabilities_entry(int port)
-{
- print_current_state(port);
-
- /* Initialize and start the SinkWaitCapTimer */
- pd_timer_enable(port, PE_TIMER_TIMEOUT, PD_T_SINK_WAIT_CAP);
-}
-
-static void pe_snk_wait_for_capabilities_run(int port)
-{
- uint8_t type;
- uint8_t cnt;
- uint8_t ext;
-
- /*
- * Transition to the PE_SNK_Evaluate_Capability state when:
- * 1) A Source_Capabilities Message is received.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(rx_emsg[port].header);
- cnt = PD_HEADER_CNT(rx_emsg[port].header);
- ext = PD_HEADER_EXT(rx_emsg[port].header);
-
- if ((ext == 0) && (cnt > 0) && (type == PD_DATA_SOURCE_CAP)) {
- set_state_pe(port, PE_SNK_EVALUATE_CAPABILITY);
- return;
- }
- }
-
- /* When the SinkWaitCapTimer times out, perform a Hard Reset. */
- if (pd_timer_is_expired(port, PE_TIMER_TIMEOUT)) {
- PE_SET_FLAG(port, PE_FLAGS_SNK_WAIT_CAP_TIMEOUT);
- set_state_pe(port, PE_SNK_HARD_RESET);
- }
-}
-
-static void pe_snk_wait_for_capabilities_exit(int port)
-{
- pd_timer_disable(port, PE_TIMER_TIMEOUT);
-}
-
-/**
- * PE_SNK_Evaluate_Capability State
- */
-static void pe_snk_evaluate_capability_entry(int port)
-{
- uint32_t *pdo = (uint32_t *)rx_emsg[port].buf;
- uint32_t num = rx_emsg[port].len >> 2;
-
- print_current_state(port);
-
- /* Reset Hard Reset counter to zero */
- pe[port].hard_reset_counter = 0;
-
- /* Set to highest revision supported by both ports. */
- prl_set_rev(port, TCPCI_MSG_SOP,
- MIN(PD_REVISION, PD_HEADER_REV(rx_emsg[port].header)));
-
- set_cable_rev(port);
-
- /* Parse source caps if they have changed */
- if (pe[port].src_cap_cnt != num ||
- memcmp(pdo, pe[port].src_caps, num << 2)) {
- /*
- * If port policy preference is to be a power role source,
- * then request a power role swap. If we'd previously queued a
- * PR swap but can now charge from this device, clear it.
- */
- if (!pd_can_charge_from_device(port, num, pdo))
- pd_request_power_swap(port);
- else
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_PR_SWAP);
- }
-
- pe_update_src_pdo_flags(port, num, pdo);
- pd_set_src_caps(port, num, pdo);
-
- /* Evaluate the options based on supplied capabilities */
- pd_process_source_cap(port, pe[port].src_cap_cnt, pe[port].src_caps);
-
- /* Device Policy Response Received */
- set_state_pe(port, PE_SNK_SELECT_CAPABILITY);
-
-#ifdef HAS_TASK_DPS
- /* Wake DPS task to evaluate the SrcCaps */
- task_wake(TASK_ID_DPS);
-#endif
-}
-
-/**
- * PE_SNK_Select_Capability State
- */
-static void pe_snk_select_capability_entry(int port)
-{
- print_current_state(port);
-
- /* Send Request */
- pe_send_request_msg(port);
- pe_sender_response_msg_entry(port);
-
- /* We are PD Connected */
- PE_SET_FLAG(port, PE_FLAGS_PD_CONNECTION);
- tc_pd_connection(port, 1);
-}
-
-static void pe_snk_select_capability_run(int port)
-{
- uint8_t type;
- uint8_t cnt;
- enum tcpci_msg_type sop;
- enum pe_msg_check msg_check;
-
- /*
- * Check the state of the message sent
- */
- msg_check = pe_sender_response_msg_run(port);
-
- /*
- * Handle discarded message
- */
- if (msg_check & PE_MSG_DISCARDED) {
- /*
- * The sent REQUEST message was discarded. This can be at
- * the start of an AMS or in the middle. Handle what to
- * do based on where we came from.
- * 1) SE_SNK_EVALUATE_CAPABILITY: sends SoftReset
- * 2) SE_SNK_READY: goes back to SNK Ready
- */
- if (get_last_state_pe(port) == PE_SNK_EVALUATE_CAPABILITY)
- pe_send_soft_reset(port, TCPCI_MSG_SOP);
- else
- set_state_pe(port, PE_SNK_READY);
- return;
- }
-
- if ((msg_check & PE_MSG_SENT) &&
- PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
- type = PD_HEADER_TYPE(rx_emsg[port].header);
- cnt = PD_HEADER_CNT(rx_emsg[port].header);
- sop = PD_HEADER_GET_SOP(rx_emsg[port].header);
-
- /*
- * Transition to the PE_SNK_Transition_Sink state when:
- * 1) An Accept Message is received from the Source.
- *
- * Transition to the PE_SNK_Wait_for_Capabilities state when:
- * 1) There is no Explicit Contract in place and
- * 2) A Reject Message is received from the Source or
- * 3) A Wait Message is received from the Source.
- *
- * Transition to the PE_SNK_Ready state when:
- * 1) There is an Explicit Contract in place and
- * 2) A Reject Message is received from the Source or
- * 3) A Wait Message is received from the Source.
- *
- * Transition to the PE_SNK_Hard_Reset state when:
- * 1) A SenderResponseTimer timeout occurs.
- */
-
- /* Only look at control messages */
- if (cnt == 0) {
- /*
- * Accept Message Received
- */
- if (type == PD_CTRL_ACCEPT) {
- /* explicit contract is now in place */
- pe_set_explicit_contract(port);
-
- set_state_pe(port, PE_SNK_TRANSITION_SINK);
-
- return;
- }
- /*
- * Reject or Wait Message Received
- */
- else if (type == PD_CTRL_REJECT ||
- type == PD_CTRL_WAIT) {
- if (type == PD_CTRL_WAIT)
- PE_SET_FLAG(port, PE_FLAGS_WAIT);
-
- pd_timer_disable(port, PE_TIMER_SINK_REQUEST);
-
- /*
- * We had a previous explicit contract, so
- * transition to PE_SNK_Ready
- */
- if (PE_CHK_FLAG(port,
- PE_FLAGS_EXPLICIT_CONTRACT))
- set_state_pe(port, PE_SNK_READY);
- /*
- * No previous explicit contract, so transition
- * to PE_SNK_Wait_For_Capabilities
- */
- else
- set_state_pe(port,
- PE_SNK_WAIT_FOR_CAPABILITIES);
- return;
- }
- /*
- * Unexpected Control Message Received
- */
- else {
- /* Send Soft Reset */
- pe_send_soft_reset(port, sop);
- return;
- }
- }
- /*
- * Unexpected Data Message
- */
- else {
- /* Send Soft Reset */
- pe_send_soft_reset(port, sop);
- return;
- }
- }
-
- /* SenderResponsetimer timeout */
- if (pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE))
- set_state_pe(port, PE_SNK_HARD_RESET);
-}
-
-void pe_snk_select_capability_exit(int port)
-{
- pe_sender_response_msg_exit(port);
-}
-
-/**
- * PE_SNK_Transition_Sink State
- */
-static void pe_snk_transition_sink_entry(int port)
-{
- print_current_state(port);
-
- /* Initialize and run PSTransitionTimer */
- pd_timer_enable(port, PE_TIMER_PS_TRANSITION, PD_T_PS_TRANSITION);
-}
-
-static void pe_snk_transition_sink_run(int port)
-{
- /*
- * Transition to the PE_SNK_Ready state when:
- * 1) A PS_RDY Message is received from the Source.
- *
- * Transition to the PE_SNK_Hard_Reset state when:
- * 1) A Protocol Error occurs.
- */
-
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- /*
- * PS_RDY message received
- */
- if ((PD_HEADER_CNT(rx_emsg[port].header) == 0) &&
- (PD_HEADER_TYPE(rx_emsg[port].header) ==
- PD_CTRL_PS_RDY)) {
- /*
- * Set first message flag to trigger a wait and add
- * jitter delay when operating in PD2.0 mode.
- */
- PE_SET_FLAG(port, PE_FLAGS_FIRST_MSG);
- pd_timer_disable(port, PE_TIMER_WAIT_AND_ADD_JITTER);
-
- /*
- * If we've successfully completed our new power
- * contract, ensure SOP' communication is enabled before
- * entering PE_SNK_READY. It may have been disabled
- * during a power role swap to avoid interoperability
- * issues with out-of-spec partners.
- */
- if (tc_is_vconn_src(port))
- tcpm_sop_prime_enable(port, true);
-
- /*
- * Evaluate port's sink caps for FRS current, if
- * already available
- */
- if (pd_get_snk_cap_cnt(port) > 0)
- dpm_evaluate_sink_fixed_pdo(port,
- *pd_get_snk_caps(port));
-
- set_state_pe(port, PE_SNK_READY);
- } else {
- /*
- * Protocol Error
- */
- set_state_pe(port, PE_SNK_HARD_RESET);
- }
- return;
- }
-
- /*
- * Timeout will lead to a Hard Reset
- */
- if (pd_timer_is_expired(port, PE_TIMER_PS_TRANSITION) &&
- pe[port].hard_reset_counter <= N_HARD_RESET_COUNT) {
- PE_SET_FLAG(port, PE_FLAGS_PS_TRANSITION_TIMEOUT);
-
- set_state_pe(port, PE_SNK_HARD_RESET);
- }
-}
-
-static void pe_snk_transition_sink_exit(int port)
-{
- /* Transition Sink's power supply to the new power level */
- pd_set_input_current_limit(port,
- pe[port].curr_limit, pe[port].supply_voltage);
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER))
- /* Set ceiling based on what's negotiated */
- charge_manager_set_ceil(port,
- CEIL_REQUESTOR_PD, pe[port].curr_limit);
-
- pd_timer_disable(port, PE_TIMER_PS_TRANSITION);
-
- if (IS_ENABLED(CONFIG_USB_PD_DPS))
- if (charge_manager_get_active_charge_port() == port)
- dps_update_stabilized_time(port);
-}
-
-
-/**
- * PE_SNK_Ready State
- */
-static void pe_snk_ready_entry(int port)
-{
- print_current_state(port);
-
- /* Ensure any message send flags are cleaned up */
- PE_CLR_FLAG(port, PE_FLAGS_READY_CLR);
-
- /* Clear DPM Current Request */
- pe[port].dpm_curr_request = 0;
-
- /*
- * On entry to the PE_SNK_Ready state as the result of a wait,
- * then do the following:
- * 1) Initialize and run the SinkRequestTimer
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_WAIT)) {
- PE_CLR_FLAG(port, PE_FLAGS_WAIT);
- pd_timer_enable(port, PE_TIMER_SINK_REQUEST,
- PD_T_SINK_REQUEST);
- }
-
- /*
- * Wait and add jitter if we are operating in PD2.0 mode and no messages
- * have been sent since enter this state.
- */
- pe_update_wait_and_add_jitter_timer(port);
-}
-
-static void pe_snk_ready_run(int port)
-{
- /*
- * Handle incoming messages before discovery and DPMs other than hard
- * reset
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- uint8_t type = PD_HEADER_TYPE(rx_emsg[port].header);
- uint8_t cnt = PD_HEADER_CNT(rx_emsg[port].header);
- uint8_t ext = PD_HEADER_EXT(rx_emsg[port].header);
- uint32_t *payload = (uint32_t *)rx_emsg[port].buf;
-
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- /* Extended Message Request */
- if (ext > 0) {
- switch (type) {
-#if defined(CONFIG_USB_PD_EXTENDED_MESSAGES) && defined(CONFIG_BATTERY)
- case PD_EXT_GET_BATTERY_CAP:
- set_state_pe(port, PE_GIVE_BATTERY_CAP);
- break;
- case PD_EXT_GET_BATTERY_STATUS:
- set_state_pe(port, PE_GIVE_BATTERY_STATUS);
- break;
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES && CONFIG_BATTERY */
- default:
- extended_message_not_supported(port, payload);
- }
- return;
- }
- /* Data Messages */
- else if (cnt > 0) {
- switch (type) {
- case PD_DATA_SOURCE_CAP:
- set_state_pe(port,
- PE_SNK_EVALUATE_CAPABILITY);
- break;
- case PD_DATA_VENDOR_DEF:
- if (PD_HEADER_TYPE(rx_emsg[port].header) ==
- PD_DATA_VENDOR_DEF) {
- if (PD_VDO_SVDM(*payload))
- set_state_pe(port,
- PE_VDM_RESPONSE);
- else
- set_state_pe(port,
- PE_HANDLE_CUSTOM_VDM_REQUEST);
- }
- break;
- case PD_DATA_BIST:
- set_state_pe(port, PE_BIST_TX);
- break;
- default:
- set_state_pe(port, PE_SEND_NOT_SUPPORTED);
- }
- return;
- }
- /* Control Messages */
- else {
- switch (type) {
- case PD_CTRL_GOOD_CRC:
- /* Do nothing */
- break;
- case PD_CTRL_PING:
- /* Do nothing */
- break;
- case PD_CTRL_GET_SOURCE_CAP:
- set_state_pe(port, PE_DR_SNK_GIVE_SOURCE_CAP);
- return;
- case PD_CTRL_GET_SINK_CAP:
- set_state_pe(port, PE_SNK_GIVE_SINK_CAP);
- return;
- case PD_CTRL_GOTO_MIN:
- set_state_pe(port, PE_SNK_TRANSITION_SINK);
- return;
- case PD_CTRL_PR_SWAP:
- set_state_pe(port,
- PE_PRS_SNK_SRC_EVALUATE_SWAP);
- return;
- case PD_CTRL_DR_SWAP:
- if (PE_CHK_FLAG(port, PE_FLAGS_MODAL_OPERATION))
- set_state_pe(port, PE_SNK_HARD_RESET);
- else
- set_state_pe(port,
- PE_DRS_EVALUATE_SWAP);
- return;
- case PD_CTRL_VCONN_SWAP:
- if (IS_ENABLED(CONFIG_USBC_VCONN))
- set_state_pe(port,
- PE_VCS_EVALUATE_SWAP);
- else
- set_state_pe(port,
- PE_SEND_NOT_SUPPORTED);
- return;
- case PD_CTRL_NOT_SUPPORTED:
- /* Do nothing */
- break;
- /*
- * USB PD 3.0 6.8.1:
- * Receiving an unexpected message shall be responded
- * to with a soft reset message.
- */
- case PD_CTRL_ACCEPT:
- case PD_CTRL_REJECT:
- case PD_CTRL_WAIT:
- case PD_CTRL_PS_RDY:
- pe_send_soft_reset(port,
- PD_HEADER_GET_SOP(rx_emsg[port].header));
- return;
- /*
- * Receiving an unknown or unsupported message
- * shall be responded to with a not supported message.
- */
- default:
- set_state_pe(port, PE_SEND_NOT_SUPPORTED);
- return;
- }
- }
- }
-
- /*
- * Make sure the PRL layer isn't busy with receiving or transmitting
- * chunked messages before attempting to transmit a new message.
- */
- if (prl_is_busy(port))
- return;
-
- if (PE_CHK_FLAG(port, PE_FLAGS_VDM_REQUEST_CONTINUE)) {
- PE_CLR_FLAG(port, PE_FLAGS_VDM_REQUEST_CONTINUE);
- set_state_pe(port, PE_VDM_REQUEST_DPM);
- return;
- }
-
- if (pd_timer_is_disabled(port, PE_TIMER_WAIT_AND_ADD_JITTER) ||
- pd_timer_is_expired(port, PE_TIMER_WAIT_AND_ADD_JITTER)) {
- PE_CLR_FLAG(port, PE_FLAGS_FIRST_MSG);
- pd_timer_disable(port, PE_TIMER_WAIT_AND_ADD_JITTER);
-
- if (pd_timer_is_expired(port, PE_TIMER_SINK_REQUEST)) {
- pd_timer_disable(port, PE_TIMER_SINK_REQUEST);
- set_state_pe(port, PE_SNK_SELECT_CAPABILITY);
- return;
- }
-
- /*
- * Handle Device Policy Manager Requests
- */
- if (sink_dpm_requests(port))
- return;
-
- /*
- * Attempt discovery if possible, and return if state was
- * changed for that discovery.
- */
- if (pe_attempt_port_discovery(port))
- return;
-
- /* No DPM requests; attempt mode entry/exit if needed */
- dpm_run(port);
-
- }
-}
-
-/**
- * PE_SNK_Hard_Reset
- */
-static void pe_snk_hard_reset_entry(int port)
-{
-#ifdef CONFIG_USB_PD_RESET_MIN_BATT_SOC
- int batt_soc;
-#endif
-
- print_current_state(port);
-
- /*
- * Note: If the SinkWaitCapTimer times out and the HardResetCounter is
- * greater than nHardResetCount the Sink Shall assume that the
- * Source is non-responsive.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_SNK_WAIT_CAP_TIMEOUT) &&
- pe[port].hard_reset_counter > N_HARD_RESET_COUNT) {
- set_state_pe(port, PE_SRC_DISABLED);
- return;
- }
-
- /*
- * If we're about to kill our active charge port and have no battery to
- * supply power, disable the PE layer instead. If we have no battery,
- * but we haven't determined our active charge port yet, also avoid
- * performing the HardReset. It might be that this port was our active
- * charge port.
- *
- * Note: On systems without batteries (ex. chromeboxes), it's preferable
- * to brown out rather than leave the port only semi-functional for a
- * customer. For systems which should have a battery, this condition is
- * not expected to be encountered by a customer.
- */
- if (IS_ENABLED(CONFIG_BATTERY) && (battery_is_present() == BP_NO) &&
- IS_ENABLED(CONFIG_CHARGE_MANAGER) &&
- ((port == charge_manager_get_active_charge_port() ||
- (charge_manager_get_active_charge_port() == CHARGE_PORT_NONE))) &&
- system_get_reset_flags() & EC_RESET_FLAG_SYSJUMP) {
- CPRINTS("C%d: Disabling port to avoid brown out, "
- "please reboot EC to enable port again", port);
- set_state_pe(port, PE_SRC_DISABLED);
- return;
-
- }
-
-#ifdef CONFIG_USB_PD_RESET_MIN_BATT_SOC
- /*
- * If the battery has not met a configured safe level for hard
- * resets, set state to PE_SRC_Disabled as a hard
- * reset could brown out the board.
- * Note this may mean that high-power chargers will stay at
- * 15W until a reset is sent, depending on boot timing.
- *
- * PE_FLAGS_SNK_WAITING_BATT flags will be cleared and
- * PE state will be switched to PE_SNK_Startup when
- * battery reaches CONFIG_USB_PD_RESET_MIN_BATT_SOC.
- * See pe_update_waiting_batt_flag() for more details.
- */
- batt_soc = usb_get_battery_soc();
-
- if (batt_soc < CONFIG_USB_PD_RESET_MIN_BATT_SOC ||
- battery_get_disconnect_state() != BATTERY_NOT_DISCONNECTED) {
- PE_SET_FLAG(port, PE_FLAGS_SNK_WAITING_BATT);
- CPRINTS("C%d: Battery low %d%%! Stay in disabled state " \
- "until battery level reaches %d%%", port, batt_soc,
- CONFIG_USB_PD_RESET_MIN_BATT_SOC);
- set_state_pe(port, PE_SRC_DISABLED);
- return;
- }
-#endif
-
- PE_CLR_FLAG(port, PE_FLAGS_SNK_WAIT_CAP_TIMEOUT |
- PE_FLAGS_VDM_REQUEST_NAKED |
- PE_FLAGS_PROTOCOL_ERROR |
- PE_FLAGS_VDM_REQUEST_BUSY);
-
- /* Request the generation of Hard Reset Signaling by the PHY Layer */
- prl_execute_hard_reset(port);
-
- /* Increment the HardResetCounter */
- pe[port].hard_reset_counter++;
-
- /*
- * Transition the Sink’s power supply to the new power level if
- * PSTransistionTimer timeout occurred.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_PS_TRANSITION_TIMEOUT)) {
- PE_CLR_FLAG(port, PE_FLAGS_PS_TRANSITION_TIMEOUT);
-
- /* Transition Sink's power supply to the new power level */
- pd_set_input_current_limit(port, pe[port].curr_limit,
- pe[port].supply_voltage);
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER))
- /* Set ceiling based on what's negotiated */
- charge_manager_set_ceil(port, CEIL_REQUESTOR_PD,
- pe[port].curr_limit);
- }
-}
-
-static void pe_snk_hard_reset_run(int port)
-{
- /*
- * Transition to the PE_SNK_Transition_to_default state when:
- * 1) The Hard Reset is complete.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_HARD_RESET_PENDING))
- return;
-
- set_state_pe(port, PE_SNK_TRANSITION_TO_DEFAULT);
-}
-
-/**
- * PE_SNK_Transition_to_default
- */
-static void pe_snk_transition_to_default_entry(int port)
-{
- print_current_state(port);
-
- /* Reset flags */
- pe[port].flags = 0;
-
- /* Reset DPM Request */
- pe[port].dpm_request = 0;
-
- /* Inform the TC Layer of Hard Reset */
- tc_hard_reset_request(port);
-}
-
-static void pe_snk_transition_to_default_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_PS_RESET_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_PS_RESET_COMPLETE);
- /* Inform the Protocol Layer that the Hard Reset is complete */
- prl_hard_reset_complete(port);
- set_state_pe(port, PE_SNK_STARTUP);
- }
-}
-
-/**
- * PE_SNK_Get_Source_Cap
- */
-static void pe_snk_get_source_cap_entry(int port)
-{
- print_current_state(port);
-
- /* Send a Get_Source_Cap Message */
- tx_emsg[port].len = 0;
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_GET_SOURCE_CAP);
-}
-
-static void pe_snk_get_source_cap_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- set_state_pe(port, PE_SNK_READY);
- }
-}
-
-/**
- * PE_SNK_Send_Soft_Reset and PE_SRC_Send_Soft_Reset
- */
-static void pe_send_soft_reset_entry(int port)
-{
- print_current_state(port);
-
- /* Reset Protocol Layer (softly) */
- prl_reset_soft(port);
-
- pe_sender_response_msg_entry(port);
-
- /*
- * Mark the temporary timer PE_TIMER_TIMEOUT as expired to limit
- * to sending a single SoftReset message.
- */
- pd_timer_enable(port, PE_TIMER_TIMEOUT, 0);
-}
-
-static void pe_send_soft_reset_run(int port)
-{
- int type;
- int cnt;
- int ext;
- enum pe_msg_check msg_check;
-
- /* Wait until protocol layer is running */
- if (!prl_is_running(port))
- return;
-
- /*
- * Protocol layer is running, so need to send a single SoftReset.
- * Use temporary timer to act as a flag to keep this as a single
- * message send.
- */
- if (!pd_timer_is_disabled(port, PE_TIMER_TIMEOUT)) {
- pd_timer_disable(port, PE_TIMER_TIMEOUT);
-
- /*
- * TODO(b/150614211): Soft reset type should match
- * unexpected incoming message type
- */
- /* Send Soft Reset message */
- send_ctrl_msg(port,
- pe[port].soft_reset_sop, PD_CTRL_SOFT_RESET);
-
- return;
- }
-
- /*
- * Check the state of the message sent
- */
- msg_check = pe_sender_response_msg_run(port);
-
- /*
- * Handle discarded message
- */
- if (msg_check == PE_MSG_DISCARDED) {
- pe_set_ready_state(port);
- return;
- }
-
- /*
- * Transition to the PE_SNK_Send_Capabilities or
- * PE_SRC_Send_Capabilities state when:
- * 1) An Accept Message has been received.
- */
- if (msg_check == PE_MSG_SENT &&
- PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(rx_emsg[port].header);
- cnt = PD_HEADER_CNT(rx_emsg[port].header);
- ext = PD_HEADER_EXT(rx_emsg[port].header);
-
- if ((ext == 0) && (cnt == 0) && (type == PD_CTRL_ACCEPT)) {
- if (pe[port].power_role == PD_ROLE_SINK)
- set_state_pe(port,
- PE_SNK_WAIT_FOR_CAPABILITIES);
- else
- set_state_pe(port,
- PE_SRC_SEND_CAPABILITIES);
- return;
- }
- }
-
- /*
- * Transition to PE_SNK_Hard_Reset or PE_SRC_Hard_Reset on Sender
- * Response Timer Timeout or Protocol Layer or 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);
-
- if (pe[port].power_role == PD_ROLE_SINK)
- set_state_pe(port, PE_SNK_HARD_RESET);
- else
- set_state_pe(port, PE_SRC_HARD_RESET);
- return;
- }
-}
-
-static void pe_send_soft_reset_exit(int port)
-{
- pe_sender_response_msg_exit(port);
- pd_timer_disable(port, PE_TIMER_TIMEOUT);
-}
-
-/**
- * PE_SNK_Soft_Reset and PE_SNK_Soft_Reset
- */
-static void pe_soft_reset_entry(int port)
-{
- print_current_state(port);
-
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_ACCEPT);
-}
-
-static void pe_soft_reset_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- if (pe[port].power_role == PD_ROLE_SINK)
- set_state_pe(port, PE_SNK_WAIT_FOR_CAPABILITIES);
- else
- set_state_pe(port, PE_SRC_SEND_CAPABILITIES);
- } else if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
- PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
-
- if (pe[port].power_role == PD_ROLE_SINK)
- set_state_pe(port, PE_SNK_HARD_RESET);
- else
- set_state_pe(port, PE_SRC_HARD_RESET);
- }
-}
-
-/**
- * PE_SRC_Not_Supported and PE_SNK_Not_Supported
- *
- * 6.7.1 Soft Reset and Protocol Error (Revision 2.0, Version 1.3)
- * An unrecognized or unsupported Message (except for a Structured VDM),
- * received in the PE_SNK_Ready or PE_SRC_Ready states, Shall Not cause
- * a Soft_Reset Message to be generated but instead a Reject Message
- * Shall be generated.
- */
-static void pe_send_not_supported_entry(int port)
-{
- print_current_state(port);
-
- /* Request the Protocol Layer to send a Not_Supported Message. */
- if (prl_get_rev(port, TCPCI_MSG_SOP) > PD_REV20)
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_NOT_SUPPORTED);
- else
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_REJECT);
-}
-
-static void pe_send_not_supported_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- pe_set_ready_state(port);
-
- }
-}
-
-/**
- * PE_SRC_Chunk_Received and PE_SNK_Chunk_Received
- *
- * 6.11.2.1.1 Architecture of Device Including Chunking Layer (Revision 3.0,
- * Version 2.0): If a PD Device or Cable Marker has no requirement to handle any
- * message requiring more than one Chunk of any Extended Message, it May omit
- * the Chunking Layer. In this case it Shall implement the
- * ChunkingNotSupportedTimer to ensure compatible operation with partners which
- * support Chunking.
- *
- * See also:
- * 6.6.18.1 ChunkingNotSupportedTimer
- * 8.3.3.6 Not Supported Message State Diagrams
- */
-__maybe_unused static void pe_chunk_received_entry(int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_REV30) ||
- IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES))
- assert(0);
-
- print_current_state(port);
- pd_timer_enable(port, PE_TIMER_CHUNKING_NOT_SUPPORTED,
- PD_T_CHUNKING_NOT_SUPPORTED);
-}
-
-__maybe_unused static void pe_chunk_received_run(int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_REV30) ||
- IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES))
- assert(0);
-
- if (pd_timer_is_expired(port, PE_TIMER_CHUNKING_NOT_SUPPORTED))
- set_state_pe(port, PE_SEND_NOT_SUPPORTED);
-}
-
-__maybe_unused static void pe_chunk_received_exit(int port)
-{
- pd_timer_disable(port, PE_TIMER_CHUNKING_NOT_SUPPORTED);
-}
-
-/**
- * PE_SRC_Ping
- */
-static void pe_src_ping_entry(int port)
-{
- print_current_state(port);
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_PING);
-}
-
-static void pe_src_ping_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- set_state_pe(port, PE_SRC_READY);
- }
-}
-
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
-/**
- * PE_Give_Battery_Cap
- */
-static void pe_give_battery_cap_entry(int port)
-{
- uint8_t *payload = rx_emsg[port].buf;
- uint16_t *msg = (uint16_t *)tx_emsg[port].buf;
-
- if (!IS_ENABLED(CONFIG_BATTERY))
- return;
- print_current_state(port);
-
- /* Set VID */
- msg[BCDB_VID] = USB_VID_GOOGLE;
-
- /* Set PID */
- msg[BCDB_PID] = CONFIG_USB_PID;
-
- if (battery_is_present()) {
- /*
- * We only have one fixed battery,
- * so make sure batt cap ref is 0.
- * This value is the first byte after the headers.
- */
- if (payload[0] != 0) {
- /* Invalid battery reference */
- msg[BCDB_DESIGN_CAP] = 0;
- msg[BCDB_FULL_CAP] = 0;
- /* Set invalid battery bit in response bit 0, byte 8 */
- msg[BCDB_BATT_TYPE] = 1;
- } else {
- /*
- * The Battery Design Capacity field shall return the
- * Battery’s design capacity in tenths of Wh. If the
- * Battery is Hot Swappable and is not present, the
- * Battery Design Capacity field shall be set to 0. If
- * the Battery is unable to report its Design Capacity,
- * it shall return 0xFFFF
- */
- msg[BCDB_DESIGN_CAP] = 0xffff;
-
- /*
- * The Battery Last Full Charge Capacity field shall
- * return the Battery’s last full charge capacity in
- * tenths of Wh. If the Battery is Hot Swappable and
- * is not present, the Battery Last Full Charge Capacity
- * field shall be set to 0. If the Battery is unable to
- * report its Design Capacity, the Battery Last Full
- * Charge Capacity field shall be set to 0xFFFF.
- */
- msg[BCDB_FULL_CAP] = 0xffff;
-
-
- if (IS_ENABLED(HAS_TASK_HOSTCMD) &&
- *host_get_memmap(EC_MEMMAP_BATTERY_VERSION) != 0) {
- int design_volt, design_cap, full_cap;
-
- design_volt = *(int *)host_get_memmap(
- EC_MEMMAP_BATT_DVLT);
- design_cap = *(int *)host_get_memmap(
- EC_MEMMAP_BATT_DCAP);
- full_cap = *(int *)host_get_memmap(
- EC_MEMMAP_BATT_LFCC);
-
- /*
- * Wh = (c * v) / 1000000
- * 10th of a Wh = Wh * 10
- */
- msg[BCDB_DESIGN_CAP] = DIV_ROUND_NEAREST(
- (design_cap * design_volt),
- 100000);
- /*
- * Wh = (c * v) / 1000000
- * 10th of a Wh = Wh * 10
- */
- msg[BCDB_FULL_CAP] = DIV_ROUND_NEAREST(
- (design_cap * full_cap),
- 100000);
- } else {
- uint32_t v;
- uint32_t c;
-
- if (battery_design_voltage(&v) == 0) {
- if (battery_design_capacity(&c) == 0) {
- /*
- * Wh = (c * v) / 1000000
- * 10th of a Wh = Wh * 10
- */
- msg[BCDB_DESIGN_CAP] =
- DIV_ROUND_NEAREST(
- (c * v),
- 100000);
- }
-
- if (battery_full_charge_capacity(&c)
- == 0) {
- /*
- * Wh = (c * v) / 1000000
- * 10th of a Wh = Wh * 10
- */
- msg[BCDB_FULL_CAP] =
- DIV_ROUND_NEAREST(
- (c * v),
- 100000);
- }
- }
-
- }
- /* Valid battery selected */
- msg[BCDB_BATT_TYPE] = 0;
- }
- } else {
- /* Battery not present indicated by 0's in the capacity */
- msg[BCDB_DESIGN_CAP] = 0;
- msg[BCDB_FULL_CAP] = 0;
- if (payload[0] != 0)
- msg[BCDB_BATT_TYPE] = 1;
- else
- msg[BCDB_BATT_TYPE] = 0;
- }
-
- /* Extended Battery Cap data is 9 bytes */
- tx_emsg[port].len = 9;
-
- send_ext_data_msg(port, TCPCI_MSG_SOP, PD_EXT_BATTERY_CAP);
-}
-
-static void pe_give_battery_cap_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- pe_set_ready_state(port);
- }
-}
-
-/**
- * PE_Give_Battery_Status
- */
-static void pe_give_battery_status_entry(int port)
-{
- uint8_t *payload = rx_emsg[port].buf;
- uint32_t *msg = (uint32_t *)tx_emsg[port].buf;
-
- if (!IS_ENABLED(CONFIG_BATTERY))
- return;
- print_current_state(port);
-
- if (battery_is_present()) {
- /*
- * We only have one fixed battery,
- * so make sure batt cap ref is 0.
- * This value is the first byte after the headers.
- */
- if (payload[0] != 0) {
- /* Invalid battery reference */
- *msg = BSDO_CAP(BSDO_CAP_UNKNOWN);
- *msg |= BSDO_INVALID;
- } else {
- uint32_t v;
- uint32_t c;
-
- *msg = BSDO_CAP(BSDO_CAP_UNKNOWN);
-
- if (IS_ENABLED(HAS_TASK_HOSTCMD) &&
- *host_get_memmap(EC_MEMMAP_BATTERY_VERSION) != 0) {
- v = *(int *)host_get_memmap(
- EC_MEMMAP_BATT_DVLT);
- c = *(int *)host_get_memmap(
- EC_MEMMAP_BATT_CAP);
-
- /*
- * Wh = (c * v) / 1000000
- * 10th of a Wh = Wh * 10
- */
- *msg = BSDO_CAP(DIV_ROUND_NEAREST((c * v),
- 100000));
- } else if (battery_design_voltage(&v) == 0 &&
- battery_remaining_capacity(&c) == 0) {
- /*
- * Wh = (c * v) / 1000000
- * 10th of a Wh = Wh * 10
- */
- *msg = BSDO_CAP(DIV_ROUND_NEAREST((c * v),
- 100000));
- }
-
- /* Battery is present */
- *msg |= BSDO_PRESENT;
-
- /*
- * For drivers that are not smart battery compliant,
- * battery_status() returns EC_ERROR_UNIMPLEMENTED and
- * the battery is assumed to be idle.
- */
- if (battery_status(&c) != 0) {
- *msg |= BSDO_IDLE; /* assume idle */
- } else {
- if (c & STATUS_FULLY_CHARGED)
- /* Fully charged */
- *msg |= BSDO_IDLE;
- else if (c & STATUS_DISCHARGING)
- /* Discharging */
- *msg |= BSDO_DISCHARGING;
- /* else battery is charging.*/
- }
- }
- } else {
- *msg = BSDO_CAP(BSDO_CAP_UNKNOWN);
- if (payload[0] != 0)
- *msg |= BSDO_INVALID;
- }
-
- /* Battery Status data is 4 bytes */
- tx_emsg[port].len = 4;
-
- send_data_msg(port, TCPCI_MSG_SOP, PD_DATA_BATTERY_STATUS);
-}
-
-static void pe_give_battery_status_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- set_state_pe(port, PE_SRC_READY);
- }
-}
-
-/**
- * PE_SRC_Send_Source_Alert and
- * PE_SNK_Send_Sink_Alert
- */
-static void pe_send_alert_entry(int port)
-{
- uint32_t *msg = (uint32_t *)tx_emsg[port].buf;
- uint32_t *len = &tx_emsg[port].len;
-
- print_current_state(port);
-
- if (pd_build_alert_msg(msg, len, pe[port].power_role) != EC_SUCCESS)
- pe_set_ready_state(port);
-
- /* Request the Protocol Layer to send Alert Message. */
- send_data_msg(port, TCPCI_MSG_SOP, PD_DATA_ALERT);
-}
-
-static void pe_send_alert_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- pe_set_ready_state(port);
- }
-}
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-
-/**
- * PE_DRS_Evaluate_Swap
- */
-static void pe_drs_evaluate_swap_entry(int port)
-{
- print_current_state(port);
-
- /* Get evaluation of Data Role Swap request from DPM */
- if (pd_check_data_swap(port, pe[port].data_role)) {
- PE_SET_FLAG(port, PE_FLAGS_ACCEPT);
- /*
- * PE_DRS_UFP_DFP_Evaluate_Swap and
- * PE_DRS_DFP_UFP_Evaluate_Swap states embedded here.
- */
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_ACCEPT);
- } else {
- /*
- * PE_DRS_UFP_DFP_Reject_Swap and PE_DRS_DFP_UFP_Reject_Swap
- * states embedded here.
- */
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_REJECT);
- }
-}
-
-static void pe_drs_evaluate_swap_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- /* Accept Message sent. Transtion to PE_DRS_Change */
- if (PE_CHK_FLAG(port, PE_FLAGS_ACCEPT)) {
- PE_CLR_FLAG(port, PE_FLAGS_ACCEPT);
- set_state_pe(port, PE_DRS_CHANGE);
- } else {
- /*
- * Message sent. Transition back to PE_SRC_Ready or
- * PE_SNK_Ready.
- */
- pe_set_ready_state(port);
- }
- }
-}
-
-/**
- * PE_DRS_Change
- */
-static void pe_drs_change_entry(int port)
-{
- print_current_state(port);
-
- /*
- * PE_DRS_UFP_DFP_Change_to_DFP and PE_DRS_DFP_UFP_Change_to_UFP
- * states embedded here.
- */
- /* Request DPM to change port data role */
- pd_request_data_swap(port);
-}
-
-static void pe_drs_change_run(int port)
-{
- /* Wait until the data role is changed */
- if (pe[port].data_role == pd_get_data_role(port))
- return;
-
- /* Update the data role */
- pe[port].data_role = pd_get_data_role(port);
-
- if (pe[port].data_role == PD_ROLE_DFP)
- PE_CLR_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP);
-
- /*
- * Port changed. Transition back to PE_SRC_Ready or
- * PE_SNK_Ready.
- */
- pe_set_ready_state(port);
-}
-
-/**
- * PE_DRS_Send_Swap
- */
-static void pe_drs_send_swap_entry(int port)
-{
- print_current_state(port);
-
- /*
- * PE_DRS_UFP_DFP_Send_Swap and PE_DRS_DFP_UFP_Send_Swap
- * states embedded here.
- */
- /* Request the Protocol Layer to send a DR_Swap Message */
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_DR_SWAP);
- pe_sender_response_msg_entry(port);
-}
-
-static void pe_drs_send_swap_run(int port)
-{
- int type;
- int cnt;
- int ext;
- enum pe_msg_check msg_check;
-
- /*
- * Check the state of the message sent
- */
- msg_check = pe_sender_response_msg_run(port);
-
- /*
- * Transition to PE_DRS_Change when:
- * 1) An Accept Message is received.
- *
- * Transition to PE_SRC_Ready or PE_SNK_Ready state when:
- * 1) A Reject Message is received.
- * 2) Or a Wait Message is received.
- */
- if ((msg_check & PE_MSG_SENT) &&
- PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(rx_emsg[port].header);
- cnt = PD_HEADER_CNT(rx_emsg[port].header);
- ext = PD_HEADER_EXT(rx_emsg[port].header);
-
- if ((ext == 0) && (cnt == 0)) {
- if (type == PD_CTRL_ACCEPT) {
- set_state_pe(port, PE_DRS_CHANGE);
- return;
- } else if ((type == PD_CTRL_REJECT) ||
- (type == PD_CTRL_WAIT) ||
- (type == PD_CTRL_NOT_SUPPORTED)) {
- pe_set_ready_state(port);
- return;
- }
- }
- }
-
- /*
- * Transition to PE_SRC_Ready or PE_SNK_Ready state when:
- * 1) the SenderResponseTimer times out.
- * 2) Message was discarded.
- */
- if ((msg_check & PE_MSG_DISCARDED) ||
- pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE))
- pe_set_ready_state(port);
-}
-
-static void pe_drs_send_swap_exit(int port)
-{
- pe_sender_response_msg_exit(port);
-}
-
-/**
- * PE_PRS_SRC_SNK_Evaluate_Swap
- */
-static void pe_prs_src_snk_evaluate_swap_entry(int port)
-{
- print_current_state(port);
-
- if (!pd_check_power_swap(port)) {
- /* PE_PRS_SRC_SNK_Reject_PR_Swap state embedded here */
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_REJECT);
- } else {
- tc_request_power_swap(port);
- /* PE_PRS_SRC_SNK_Accept_Swap state embedded here */
- PE_SET_FLAG(port, PE_FLAGS_ACCEPT);
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_ACCEPT);
- }
-}
-
-static void pe_prs_src_snk_evaluate_swap_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- if (PE_CHK_FLAG(port, PE_FLAGS_ACCEPT)) {
- PE_CLR_FLAG(port, PE_FLAGS_ACCEPT);
-
- /*
- * Clear any pending DPM power role swap request so we
- * don't trigger a power role swap request back to src
- * power role.
- */
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_PR_SWAP);
- /*
- * Power Role Swap OK, transition to
- * PE_PRS_SRC_SNK_Transition_to_off
- */
- set_state_pe(port, PE_PRS_SRC_SNK_TRANSITION_TO_OFF);
- } else {
- /* Message sent, return to PE_SRC_Ready */
- set_state_pe(port, PE_SRC_READY);
- }
- }
-}
-
-/**
- * PE_PRS_SRC_SNK_Transition_To_Off
- */
-static void pe_prs_src_snk_transition_to_off_entry(int port)
-{
- print_current_state(port);
-
- /* Contract is invalid */
- pe_invalidate_explicit_contract(port);
-
- /* Tell TypeC to power off the source */
- tc_src_power_off(port);
-
- pd_timer_enable(port, PE_TIMER_PS_SOURCE,
- PD_POWER_SUPPLY_TURN_OFF_DELAY);
-}
-
-static void pe_prs_src_snk_transition_to_off_run(int port)
-{
- /*
- * This is a non-interruptible AMS and power is transitioning - hard
- * reset on interruption.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- tc_pr_swap_complete(port, 0);
- set_state_pe(port, PE_SRC_HARD_RESET);
- }
-
- /* Give time for supply to power off */
- if (pd_timer_is_expired(port, PE_TIMER_PS_SOURCE) &&
- pd_check_vbus_level(port, VBUS_SAFE0V))
- set_state_pe(port, PE_PRS_SRC_SNK_ASSERT_RD);
-}
-
-static void pe_prs_src_snk_transition_to_off_exit(int port)
-{
- pd_timer_disable(port, PE_TIMER_PS_SOURCE);
-}
-
-/**
- * PE_PRS_SRC_SNK_Assert_Rd
- */
-static void pe_prs_src_snk_assert_rd_entry(int port)
-{
- print_current_state(port);
-
- /* Tell TypeC to swap from Attached.SRC to Attached.SNK */
- tc_prs_src_snk_assert_rd(port);
-}
-
-static void pe_prs_src_snk_assert_rd_run(int port)
-{
- /* Wait until Rd is asserted */
- if (tc_is_attached_snk(port))
- set_state_pe(port, PE_PRS_SRC_SNK_WAIT_SOURCE_ON);
-}
-
-/**
- * PE_PRS_SRC_SNK_Wait_Source_On
- */
-static void pe_prs_src_snk_wait_source_on_entry(int port)
-{
- print_current_state(port);
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_PS_RDY);
-}
-
-static void pe_prs_src_snk_wait_source_on_run(int port)
-{
- if (pd_timer_is_disabled(port, PE_TIMER_PS_SOURCE) &&
- PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- /* Update pe power role */
- pe[port].power_role = pd_get_power_role(port);
- pd_timer_enable(port, PE_TIMER_PS_SOURCE, PD_T_PS_SOURCE_ON);
- }
-
- /*
- * Transition to PE_SNK_Startup when:
- * 1) A PS_RDY Message is received.
- */
- if (!pd_timer_is_disabled(port, PE_TIMER_PS_SOURCE) &&
- PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- int type = PD_HEADER_TYPE(rx_emsg[port].header);
- int cnt = PD_HEADER_CNT(rx_emsg[port].header);
- int ext = PD_HEADER_EXT(rx_emsg[port].header);
-
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- if ((ext == 0) && (cnt == 0) && (type == PD_CTRL_PS_RDY)) {
- PE_SET_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE);
- set_state_pe(port, PE_SNK_STARTUP);
- } else {
- int sop = PD_HEADER_GET_SOP(rx_emsg[port].header);
- /*
- * USB PD 3.0 6.8.1:
- * Receiving an unexpected message shall be responded
- * to with a soft reset message.
- */
- pe_send_soft_reset(port, sop);
- }
- return;
- }
-
- /*
- * Transition to ErrorRecovery state when:
- * 1) The PSSourceOnTimer times out.
- * 2) PS_RDY not sent after retries.
- */
- if (pd_timer_is_expired(port, PE_TIMER_PS_SOURCE) ||
- 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_prs_src_snk_wait_source_on_exit(int port)
-{
- pd_timer_disable(port, PE_TIMER_PS_SOURCE);
- tc_pr_swap_complete(port,
- PE_CHK_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE));
-}
-
-/**
- * PE_PRS_SRC_SNK_Send_Swap
- */
-static void pe_prs_src_snk_send_swap_entry(int port)
-{
- print_current_state(port);
-
- /* Making an attempt to PR_Swap, clear we were possibly waiting */
- pd_timer_disable(port, PE_TIMER_PR_SWAP_WAIT);
-
- /* Request the Protocol Layer to send a PR_Swap Message. */
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_PR_SWAP);
- pe_sender_response_msg_entry(port);
-}
-
-static void pe_prs_src_snk_send_swap_run(int port)
-{
- int type;
- int cnt;
- int ext;
- enum pe_msg_check msg_check;
-
- /*
- * Check the state of the message sent
- */
- msg_check = pe_sender_response_msg_run(port);
-
- /*
- * Transition to PE_PRS_SRC_SNK_Transition_To_Off when:
- * 1) An Accept Message is received.
- *
- * Transition to PE_SRC_Ready state when:
- * 1) A Reject Message is received.
- * 2) Or a Wait Message is received.
- */
- if ((msg_check & PE_MSG_SENT) &&
- PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(rx_emsg[port].header);
- cnt = PD_HEADER_CNT(rx_emsg[port].header);
- ext = PD_HEADER_EXT(rx_emsg[port].header);
-
- if ((ext == 0) && (cnt == 0)) {
- if (type == PD_CTRL_ACCEPT) {
- pe[port].src_snk_pr_swap_counter = 0;
- tc_request_power_swap(port);
- set_state_pe(port,
- PE_PRS_SRC_SNK_TRANSITION_TO_OFF);
- } else if (type == PD_CTRL_REJECT) {
- pe[port].src_snk_pr_swap_counter = 0;
- set_state_pe(port, PE_SRC_READY);
- } else if (type == PD_CTRL_WAIT) {
- if (pe[port].src_snk_pr_swap_counter <
- N_SNK_SRC_PR_SWAP_COUNT) {
- PE_SET_FLAG(port,
- PE_FLAGS_WAITING_PR_SWAP);
- pd_timer_enable(port,
- PE_TIMER_PR_SWAP_WAIT,
- PD_T_PR_SWAP_WAIT);
- }
- pe[port].src_snk_pr_swap_counter++;
- set_state_pe(port, PE_SRC_READY);
- }
- return;
- }
- }
-
- /*
- * Transition to PE_SRC_Ready state when:
- * 1) Or the SenderResponseTimer times out.
- * 2) Message was discarded.
- */
- if ((msg_check & PE_MSG_DISCARDED) ||
- pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE))
- set_state_pe(port, PE_SRC_READY);
-}
-
-static void pe_prs_src_snk_send_swap_exit(int port)
-{
- pe_sender_response_msg_exit(port);
-}
-
-/**
- * PE_PRS_SNK_SRC_Evaluate_Swap
- */
-static void pe_prs_snk_src_evaluate_swap_entry(int port)
-{
- print_current_state(port);
-
- /*
- * Cancel any pending PR swap request due to a received Wait since the
- * partner just sent us a PR swap message.
- */
- PE_CLR_FLAG(port, PE_FLAGS_WAITING_PR_SWAP);
- pe[port].src_snk_pr_swap_counter = 0;
-
- if (!pd_check_power_swap(port)) {
- /* PE_PRS_SNK_SRC_Reject_Swap state embedded here */
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_REJECT);
- } else {
- tc_request_power_swap(port);
- /* PE_PRS_SNK_SRC_Accept_Swap state embedded here */
- PE_SET_FLAG(port, PE_FLAGS_ACCEPT);
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_ACCEPT);
- }
-}
-
-static void pe_prs_snk_src_evaluate_swap_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- if (PE_CHK_FLAG(port, PE_FLAGS_ACCEPT)) {
- PE_CLR_FLAG(port, PE_FLAGS_ACCEPT);
-
- /*
- * Clear any pending DPM power role swap request so we
- * don't trigger a power role swap request back to sink
- * power role.
- */
- PE_CLR_DPM_REQUEST(port, DPM_REQUEST_PR_SWAP);
- /*
- * Accept message sent, transition to
- * PE_PRS_SNK_SRC_Transition_to_off
- */
- set_state_pe(port, PE_PRS_SNK_SRC_TRANSITION_TO_OFF);
- } else {
- /* Message sent, return to PE_SNK_Ready */
- set_state_pe(port, PE_SNK_READY);
- }
- }
-
- if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
- PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
- /*
- * Protocol Error occurs while PR swap, this may
- * brown out if the port-parnter can't hold VBUS
- * for tSrcTransition. Notify TC that we end the PR
- * swap and start to watch VBUS.
- *
- * TODO(b:155181980): issue soft reset on protocol error.
- */
- tc_pr_swap_complete(port, 0);
- }
-}
-
-/**
- * PE_PRS_SNK_SRC_Transition_To_Off
- * PE_FRS_SNK_SRC_Transition_To_Off
- *
- * NOTE: Shared action code used for Power Role Swap and Fast Role Swap
- */
-static void pe_prs_snk_src_transition_to_off_entry(int port)
-{
- print_current_state(port);
-
- if (!IS_ENABLED(CONFIG_USB_PD_REV30) ||
- !pe_in_frs_mode(port))
- tc_snk_power_off(port);
-
- pd_timer_enable(port, PE_TIMER_PS_SOURCE, PD_T_PS_SOURCE_OFF);
-}
-
-static void pe_prs_snk_src_transition_to_off_run(int port)
-{
- int type;
- int cnt;
- int ext;
-
- /*
- * Transition to ErrorRecovery state when:
- * 1) The PSSourceOffTimer times out.
- */
- if (pd_timer_is_expired(port, PE_TIMER_PS_SOURCE))
- set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY);
-
- /*
- * Transition to PE_PRS_SNK_SRC_Assert_Rp when:
- * 1) An PS_RDY Message is received.
- */
- else if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(rx_emsg[port].header);
- cnt = PD_HEADER_CNT(rx_emsg[port].header);
- ext = PD_HEADER_EXT(rx_emsg[port].header);
-
- if ((ext == 0) && (cnt == 0) && (type == PD_CTRL_PS_RDY)) {
- /*
- * FRS: We are always ready to drive vSafe5v, so just
- * skip PE_FRS_SNK_SRC_Vbus_Applied and go direct to
- * PE_FRS_SNK_SRC_Assert_Rp
- */
- set_state_pe(port, PE_PRS_SNK_SRC_ASSERT_RP);
- }
- }
-}
-
-static void pe_prs_snk_src_transition_to_off_exit(int port)
-{
- pd_timer_disable(port, PE_TIMER_PS_SOURCE);
-}
-
-/**
- * PE_PRS_SNK_SRC_Assert_Rp
- * PE_FRS_SNK_SRC_Assert_Rp
- *
- * NOTE: Shared action code used for Power Role Swap and Fast Role Swap
- */
-static void pe_prs_snk_src_assert_rp_entry(int port)
-{
- print_current_state(port);
-
- /*
- * Tell TypeC to Power/Fast Role Swap (PRS/FRS) from
- * Attached.SNK to Attached.SRC
- */
- tc_prs_snk_src_assert_rp(port);
-}
-
-static void pe_prs_snk_src_assert_rp_run(int port)
-{
- /* Wait until TypeC is in the Attached.SRC state */
- if (tc_is_attached_src(port)) {
- if (!IS_ENABLED(CONFIG_USB_PD_REV30) ||
- !pe_in_frs_mode(port)) {
- /* Contract is invalid now */
- pe_invalidate_explicit_contract(port);
- }
- set_state_pe(port, PE_PRS_SNK_SRC_SOURCE_ON);
- }
-}
-
-/**
- * PE_PRS_SNK_SRC_Source_On
- * PE_FRS_SNK_SRC_Source_On
- *
- * NOTE: Shared action code used for Power Role Swap and Fast Role Swap
- */
-static void pe_prs_snk_src_source_on_entry(int port)
-{
- print_current_state(port);
-
- /*
- * VBUS was enabled when the TypeC state machine entered
- * Attached.SRC state
- */
- pd_timer_enable(port, PE_TIMER_PS_SOURCE,
- PD_POWER_SUPPLY_TURN_ON_DELAY);
-}
-
-static void pe_prs_snk_src_source_on_run(int port)
-{
- /* Wait until power supply turns on */
- if (!pd_timer_is_disabled(port, PE_TIMER_PS_SOURCE)) {
- if (!pd_timer_is_expired(port, PE_TIMER_PS_SOURCE))
- return;
-
- /* update pe power role */
- pe[port].power_role = pd_get_power_role(port);
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_PS_RDY);
- /* reset timer so PD_CTRL_PS_RDY isn't sent again */
- pd_timer_disable(port, PE_TIMER_PS_SOURCE);
- }
-
- /*
- * Transition to ErrorRecovery state when:
- * 1) On protocol error
- */
- else if (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);
- }
-
- else if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- /* Run swap source timer on entry to pe_src_startup */
- PE_SET_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE);
- set_state_pe(port, PE_SRC_STARTUP);
- }
-}
-
-static void pe_prs_snk_src_source_on_exit(int port)
-{
- pd_timer_disable(port, PE_TIMER_PS_SOURCE);
- tc_pr_swap_complete(port,
- PE_CHK_FLAG(port, PE_FLAGS_PR_SWAP_COMPLETE));
-}
-
-/**
- * PE_PRS_SNK_SRC_Send_Swap
- * PE_FRS_SNK_SRC_Send_Swap
- *
- * NOTE: Shared action code used for Power Role Swap and Fast Role Swap
- */
-static void pe_prs_snk_src_send_swap_entry(int port)
-{
- print_current_state(port);
-
- /*
- * PRS_SNK_SRC_SEND_SWAP
- * Request the Protocol Layer to send a PR_Swap Message.
- *
- * FRS_SNK_SRC_SEND_SWAP
- * Hardware should have turned off sink power and started
- * bringing Vbus to vSafe5.
- * Request the Protocol Layer to send a FR_Swap Message.
- */
- if (IS_ENABLED(CONFIG_USB_PD_REV30)) {
- send_ctrl_msg(port,
- TCPCI_MSG_SOP,
- pe_in_frs_mode(port)
- ? PD_CTRL_FR_SWAP
- : PD_CTRL_PR_SWAP);
- } else {
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_PR_SWAP);
- }
- pe_sender_response_msg_entry(port);
-}
-
-static void pe_prs_snk_src_send_swap_run(int port)
-{
- int type;
- int cnt;
- int ext;
- enum pe_msg_check msg_check;
-
- /*
- * Check the state of the message sent
- */
- msg_check = pe_sender_response_msg_run(port);
-
- /*
- * Handle discarded message
- */
- if (msg_check & PE_MSG_DISCARDED) {
- if (pe_in_frs_mode(port))
- set_state_pe(port, PE_SNK_HARD_RESET);
- else
- set_state_pe(port, PE_SNK_READY);
- return;
- }
-
- /*
- * Transition to PE_PRS_SNK_SRC_Transition_to_off when:
- * 1) An Accept Message is received.
- *
- * PRS: Transition to PE_SNK_Ready state when:
- * FRS: Transition to ErrorRecovery state when:
- * 1) A Reject Message is received.
- * 2) Or a Wait Message is received.
- */
- if ((msg_check & PE_MSG_SENT) &&
- PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(rx_emsg[port].header);
- cnt = PD_HEADER_CNT(rx_emsg[port].header);
- ext = PD_HEADER_EXT(rx_emsg[port].header);
-
- if ((ext == 0) && (cnt == 0)) {
- if (type == PD_CTRL_ACCEPT) {
- tc_request_power_swap(port);
- set_state_pe(port,
- PE_PRS_SNK_SRC_TRANSITION_TO_OFF);
- } else if ((type == PD_CTRL_REJECT) ||
- (type == PD_CTRL_WAIT)) {
- if (IS_ENABLED(CONFIG_USB_PD_REV30))
- set_state_pe(port,
- pe_in_frs_mode(port)
- ? PE_WAIT_FOR_ERROR_RECOVERY
- : PE_SNK_READY);
- else
- set_state_pe(port, PE_SNK_READY);
- }
- return;
- }
- }
-
- /*
- * PRS: Transition to PE_SNK_Ready state when:
- * FRS: Transition to ErrorRecovery state when:
- * 1) The SenderResponseTimer times out.
- */
- if (pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE)) {
- if (IS_ENABLED(CONFIG_USB_PD_REV30))
- set_state_pe(port,
- pe_in_frs_mode(port)
- ? PE_WAIT_FOR_ERROR_RECOVERY
- : PE_SNK_READY);
- else
- set_state_pe(port, PE_SNK_READY);
- return;
- }
- /*
- * FRS Only: Transition to ErrorRecovery state when:
- * 2) The FR_Swap Message is not sent after retries (a GoodCRC Message
- * has not been received). A soft reset Shall Not be initiated in
- * this case.
- */
- if (IS_ENABLED(CONFIG_USB_PD_REV30) &&
- pe_in_frs_mode(port) &&
- 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);
- }
-}
-
-static void pe_prs_snk_src_send_swap_exit(int port)
-{
- pe_sender_response_msg_exit(port);
-}
-
-/**
- * PE_FRS_SNK_SRC_Start_AMS
- */
-__maybe_unused static void pe_frs_snk_src_start_ams_entry(int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_REV30))
- assert(0);
-
- print_current_state(port);
-
- /* Contract is invalid now */
- pe_invalidate_explicit_contract(port);
-
- /* Inform Protocol Layer this is start of AMS */
- PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS);
-
- /* Shared PRS/FRS code, indicate FRS path */
- PE_SET_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH);
- set_state_pe(port, PE_PRS_SNK_SRC_SEND_SWAP);
-}
-
-/**
- * PE_PRS_FRS_SHARED
- */
-__maybe_unused static void pe_prs_frs_shared_entry(int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_REV30))
- assert(0);
-
- /*
- * Shared PRS/FRS code, assume PRS path
- *
- * This is the super state entry. It will be called before
- * the first entry state to get into the PRS/FRS path.
- * For FRS, PE_FRS_SNK_SRC_START_AMS entry will be called
- * after this and that will set for the FRS path.
- */
- PE_CLR_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH);
-}
-
-__maybe_unused static void pe_prs_frs_shared_exit(int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_REV30))
- assert(0);
-
- /*
- * Shared PRS/FRS code, when not in shared path
- * indicate PRS path
- */
- PE_CLR_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH);
-}
-
-/**
- * PE_BIST_TX
- */
-static void pe_bist_tx_entry(int port)
-{
- uint32_t *payload = (uint32_t *)rx_emsg[port].buf;
- uint8_t mode = BIST_MODE(payload[0]);
- int vbus_mv;
- int ibus_ma;
-
- print_current_state(port);
-
- /* Get the current nominal VBUS value */
- if (pe[port].power_role == PD_ROLE_SOURCE) {
- const uint32_t *src_pdo;
- uint32_t unused;
-
- dpm_get_source_pdo(&src_pdo, port);
- pd_extract_pdo_power(src_pdo[pe[port].requested_idx - 1],
- &ibus_ma, &vbus_mv, &unused);
- } else {
- vbus_mv = pe[port].supply_voltage;
- }
-
- /* If VBUS is not at vSafe5V, then don't enter BIST test mode */
- if (vbus_mv != PD_V_SAFE5V_NOM) {
- pe_set_ready_state(port);
- return;
- }
-
- if (mode == BIST_CARRIER_MODE_2) {
- /*
- * PE_BIST_Carrier_Mode embedded here.
- * See PD 3.0 section 6.4.3.1 BIST Carrier Mode 2: With a BIST
- * Carrier Mode 2 BIST Data Object, the UUT Shall send out a
- * continuous string of BMC-encoded alternating "1"s and “0”s.
- * The UUT Shall exit the Continuous BIST Mode within
- * tBISTContMode of this Continuous BIST Mode being enabled.
- */
- send_ctrl_msg(port, TCPCI_MSG_TX_BIST_MODE_2, 0);
- pd_timer_enable(port, PE_TIMER_BIST_CONT_MODE,
- PD_T_BIST_CONT_MODE);
- } else if (mode == BIST_TEST_DATA) {
- /*
- * See PD 3.0 section 6.4.3.2 BIST Test Data:
- * With a BIST Test Data BIST Data Object, the UUT Shall return
- * a GoodCRC Message and Shall enter a test mode in which it
- * sends no further Messages except for GoodCRC Messages in
- * response to received Messages.... The test Shall be ended by
- * sending Hard Reset Signaling to reset the UUT.
- */
- if (tcpc_set_bist_test_mode(port, true) != EC_SUCCESS)
- CPRINTS("C%d: Failed to enter BIST Test Mode", port);
- } else {
- /* Ignore unsupported BIST messages. */
- pe_set_ready_state(port);
- return;
- }
-}
-
-static void pe_bist_tx_run(int port)
-{
- if (pd_timer_is_expired(port, PE_TIMER_BIST_CONT_MODE)) {
- /*
- * Entry point to disable BIST in TCPC if that's not already
- * handled automatically by the TCPC. Unless this method is
- * implemented in a TCPM driver, this function does nothing.
- */
- tcpm_reset_bist_type_2(port);
-
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_TRANSITION_TO_DEFAULT);
- else
- set_state_pe(port, PE_SNK_TRANSITION_TO_DEFAULT);
- } else {
- /*
- * We are in test data mode and no further Messages except for
- * GoodCRC Messages in response to received Messages will
- * be sent.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED))
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
- }
-}
-
-static void pe_bist_tx_exit(int port)
-{
- pd_timer_disable(port, PE_TIMER_BIST_CONT_MODE);
-}
-
-/**
- * Give_Sink_Cap Message
- */
-static void pe_snk_give_sink_cap_entry(int port)
-{
- print_current_state(port);
-
- /* Send a Sink_Capabilities Message */
- tx_emsg[port].len = pd_snk_pdo_cnt * 4;
- memcpy(tx_emsg[port].buf, (uint8_t *)pd_snk_pdo, tx_emsg[port].len);
- send_data_msg(port, TCPCI_MSG_SOP, PD_DATA_SINK_CAP);
-}
-
-static void pe_snk_give_sink_cap_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- pe_set_ready_state(port);
- return;
- }
-
- if (pe_check_outgoing_discard(port))
- return;
-}
-
-/**
- * Wait For Error Recovery
- */
-static void pe_wait_for_error_recovery_entry(int port)
-{
- print_current_state(port);
- tc_start_error_recovery(port);
-}
-
-static void pe_wait_for_error_recovery_run(int port)
-{
- /* Stay here until error recovery is complete */
-}
-
-/**
- * PE_Handle_Custom_Vdm_Request
- */
-static void pe_handle_custom_vdm_request_entry(int port)
-{
- /* Get the message */
- uint32_t *payload = (uint32_t *)rx_emsg[port].buf;
- int cnt = PD_HEADER_CNT(rx_emsg[port].header);
- int sop = PD_HEADER_GET_SOP(rx_emsg[port].header);
- int rlen = 0;
- uint32_t *rdata;
-
- print_current_state(port);
-
- /* This is an Interruptible AMS */
- PE_SET_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
-
- rlen = pd_custom_vdm(port, cnt, payload, &rdata);
- if (rlen > 0) {
- tx_emsg[port].len = rlen * 4;
- memcpy(tx_emsg[port].buf, (uint8_t *)rdata, tx_emsg[port].len);
- send_data_msg(port, sop, PD_DATA_VENDOR_DEF);
- } else {
- if (prl_get_rev(port, TCPCI_MSG_SOP) > PD_REV20) {
- set_state_pe(port, PE_SEND_NOT_SUPPORTED);
- } else {
- PE_CLR_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
- pe_set_ready_state(port);
- }
- }
-}
-
-static void pe_handle_custom_vdm_request_run(int port)
-{
- /* Wait for ACCEPT, WAIT or Reject message to send. */
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- /*
- * Message sent. Transition back to
- * PE_SRC_Ready or PE_SINK_Ready
- */
- pe_set_ready_state(port);
- }
-}
-
-static void pe_handle_custom_vdm_request_exit(int port)
-{
- PE_CLR_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
-}
-
-static enum vdm_response_result parse_vdm_response_common(int port)
-{
- /* Retrieve the message information */
- uint32_t *payload;
- int sop;
- uint8_t type;
- uint8_t cnt;
- uint8_t ext;
-
- if (!PE_CHK_REPLY(port))
- return VDM_RESULT_WAITING;
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- payload = (uint32_t *)rx_emsg[port].buf;
- sop = PD_HEADER_GET_SOP(rx_emsg[port].header);
- type = PD_HEADER_TYPE(rx_emsg[port].header);
- cnt = PD_HEADER_CNT(rx_emsg[port].header);
- ext = PD_HEADER_EXT(rx_emsg[port].header);
-
- if (sop == pe[port].tx_type && type == PD_DATA_VENDOR_DEF && cnt >= 1
- && ext == 0) {
- if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_ACK &&
- cnt >= pe[port].vdm_ack_min_data_objects) {
- /* Handle ACKs in state-specific code. */
- return VDM_RESULT_ACK;
- } else if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_NAK) {
- /* Handle NAKs in state-specific code. */
- return VDM_RESULT_NAK;
- } else if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_BUSY) {
- /*
- * Don't fill in the discovery field so we re-probe in
- * tVDMBusy
- */
- CPRINTS("C%d: Partner BUSY, request will be retried",
- port);
- pd_timer_enable(port, PE_TIMER_DISCOVER_IDENTITY,
- PD_T_VDM_BUSY);
-
- return VDM_RESULT_NO_ACTION;
- } else if (PD_VDO_CMDT(payload[0]) == CMDT_INIT) {
- /*
- * Unexpected VDM REQ received. Let Src.Ready or
- * Snk.Ready handle it.
- */
- PE_SET_FLAG(port, PE_FLAGS_MSG_RECEIVED);
- return VDM_RESULT_NO_ACTION;
- }
-
- /*
- * Partner gave us an incorrect size or command; mark discovery
- * as failed.
- */
- CPRINTS("C%d: Unexpected VDM response: 0x%04x 0x%04x",
- port, rx_emsg[port].header, payload[0]);
- return VDM_RESULT_NAK;
- } else if (sop == pe[port].tx_type && ext == 0 && cnt == 0 &&
- type == PD_CTRL_NOT_SUPPORTED) {
- /*
- * A NAK would be more expected here, but Not Supported is still
- * allowed with the same meaning.
- */
- return VDM_RESULT_NAK;
- }
-
- /* Unexpected Message Received. Src.Ready or Snk.Ready can handle it. */
- PE_SET_FLAG(port, PE_FLAGS_MSG_RECEIVED);
- return VDM_RESULT_NO_ACTION;
-}
-
-/**
- * PE_VDM_SEND_REQUEST
- * Shared parent to manage VDM timer and other shared parts of the VDM request
- * process
- */
-static void pe_vdm_send_request_entry(int port)
-{
- if (pe[port].tx_type == TCPCI_MSG_INVALID) {
- if (IS_ENABLED(USB_PD_DEBUG_LABELS))
- CPRINTS("C%d: %s: Tx type expected to be set, "
- "returning",
- port, pe_state_names[get_state_pe(port)]);
- set_state_pe(port, get_last_state_pe(port));
- return;
- }
-
- if ((pe[port].tx_type == TCPCI_MSG_SOP_PRIME ||
- pe[port].tx_type == TCPCI_MSG_SOP_PRIME_PRIME) &&
- !tc_is_vconn_src(port) && port_discovery_vconn_swap_policy(port,
- PE_FLAGS_VCONN_SWAP_TO_ON)) {
- if (port_try_vconn_swap(port))
- return;
- }
-
- /* All VDM sequences are Interruptible */
- PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS |
- PE_FLAGS_INTERRUPTIBLE_AMS);
-}
-
-static void pe_vdm_send_request_run(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE) &&
- pd_timer_is_disabled(port, PE_TIMER_VDM_RESPONSE)) {
- /* Message was sent */
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- /* Start no response timer */
- /* TODO(b/155890173): Support DPM-supplied timeout */
- pd_timer_enable(port, PE_TIMER_VDM_RESPONSE,
- PD_T_VDM_SNDR_RSP);
- }
-
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) {
- /*
- * Go back to ready on first AMS message discard
- * (ready states will clear the discard flag)
- */
- pe_set_ready_state(port);
- return;
- }
-
- /*
- * Check the VDM timer, child will be responsible for processing
- * messages and reacting appropriately to unexpected messages.
- */
- if (pd_timer_is_expired(port, PE_TIMER_VDM_RESPONSE)) {
- CPRINTF("VDM %s Response Timeout\n",
- pe[port].tx_type == TCPCI_MSG_SOP ?
- "Port" : "Cable");
- /*
- * Flag timeout so child state can mark appropriate discovery
- * item as failed.
- */
- PE_SET_FLAG(port, PE_FLAGS_VDM_REQUEST_TIMEOUT);
-
- set_state_pe(port, get_last_state_pe(port));
- }
-}
-
-static void pe_vdm_send_request_exit(int port)
-{
- /*
- * Clear TX complete in case child called set_state_pe() before parent
- * could process transmission
- */
- PE_CLR_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
-
- /* Invalidate TX type so it must be set before next call */
- pe[port].tx_type = TCPCI_MSG_INVALID;
-
- pd_timer_disable(port, PE_TIMER_VDM_RESPONSE);
-}
-
-/**
- * PE_VDM_IDENTITY_REQUEST_CBL
- * Combination of PE_INIT_PORT_VDM_Identity_Request State specific to the
- * cable and PE_SRC_VDM_Identity_Request State.
- * pe[port].tx_type must be set (to SOP') prior to entry.
- */
-static void pe_vdm_identity_request_cbl_entry(int port)
-{
- uint32_t *msg = (uint32_t *)tx_emsg[port].buf;
-
- print_current_state(port);
-
- if (!pe_can_send_sop_prime(port)) {
- /*
- * The parent state already tried to enable SOP' traffic. If it
- * is still disabled, there's nothing left to try.
- */
- pd_set_identity_discovery(port, pe[port].tx_type, PD_DISC_FAIL);
- set_state_pe(port, get_last_state_pe(port));
- return;
- }
-
- msg[0] = VDO(USB_SID_PD, 1,
- VDO_SVDM_VERS(pd_get_vdo_ver(port, pe[port].tx_type)) |
- CMD_DISCOVER_IDENT);
- tx_emsg[port].len = sizeof(uint32_t);
-
- send_data_msg(port, pe[port].tx_type, PD_DATA_VENDOR_DEF);
-
- pe[port].discover_identity_counter++;
-
- /*
- * Valid DiscoverIdentity responses should have at least 4 objects
- * (header, ID header, Cert Stat, Product VDO).
- */
- pe[port].vdm_ack_min_data_objects = 4;
-}
-
-static void pe_vdm_identity_request_cbl_run(int port)
-{
- /* Retrieve the message information */
- uint32_t *payload = (uint32_t *) rx_emsg[port].buf;
- int sop = PD_HEADER_GET_SOP(rx_emsg[port].header);
- uint8_t type = PD_HEADER_TYPE(rx_emsg[port].header);
- uint8_t cnt = PD_HEADER_CNT(rx_emsg[port].header);
- uint8_t ext = PD_HEADER_EXT(rx_emsg[port].header);
-
- switch (parse_vdm_response_common(port)) {
- case VDM_RESULT_WAITING:
- /*
- * The common code didn't parse a message. Handle protocol
- * errors; otherwise, continue waiting.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
- /*
- * No Good CRC: See section 6.4.4.3.1 - Discover
- * Identity.
- *
- * Discover Identity Command request sent to SOP' Shall
- * Not cause a Soft Reset if a GoodCRC Message response
- * is not returned since this can indicate a non-PD
- * Capable cable.
- */
- PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
- set_state_pe(port, get_last_state_pe(port));
- }
- return;
- case VDM_RESULT_NO_ACTION:
- /*
- * If the received message doesn't change the discovery state,
- * there is nothing to do but return to the previous ready
- * state.
- */
- if (get_last_state_pe(port) == PE_SRC_DISCOVERY &&
- (sop != pe[port].tx_type ||
- type != PD_DATA_VENDOR_DEF ||
- cnt == 0 || ext != 0)) {
- /*
- * Unexpected non-VDM received: Before an explicit
- * contract, an unexpected message shall generate a soft
- * reset using the SOP* of the incoming message.
- */
- pe_send_soft_reset(port, sop);
- return;
- }
- break;
- case VDM_RESULT_ACK:
- /* PE_INIT_PORT_VDM_Identity_ACKed embedded here */
- dfp_consume_identity(port, sop, cnt, payload);
-
- /*
- * Note: If port partner runs PD 2.0, we must use PD 2.0 to
- * communicate with the cable plug when in an explicit contract.
- *
- * PD Spec Table 6-2: Revision Interoperability during an
- * Explicit Contract
- */
- if (prl_get_rev(port, TCPCI_MSG_SOP) != PD_REV20)
- prl_set_rev(port, sop,
- PD_HEADER_REV(rx_emsg[port].header));
- break;
- case VDM_RESULT_NAK:
- /* PE_INIT_PORT_VDM_IDENTITY_NAKed embedded here */
- pd_set_identity_discovery(port, pe[port].tx_type, PD_DISC_FAIL);
- break;
- }
-
- /* Return to calling state (PE_{SRC,SNK}_Ready or PE_SRC_Discovery) */
- set_state_pe(port, get_last_state_pe(port));
-}
-
-static void pe_vdm_identity_request_cbl_exit(int port)
-{
- /*
- * When cable GoodCRCs but does not reply, down-rev to PD 2.0 and try
- * again.
- *
- * PD 3.0 Rev 2.0 6.2.1.1.5 Specification Revision
- *
- * "When a Cable Plug does not respond to a Revision 3.0 Discover
- * Identity REQ with a Discover Identity ACK or BUSY the Vconn Source
- * May repeat steps 1-4 using a Revision 2.0 Discover Identity REQ in
- * step 1 before establishing that there is no Cable Plug to
- * communicate with"
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_VDM_REQUEST_TIMEOUT)) {
- PE_CLR_FLAG(port, PE_FLAGS_VDM_REQUEST_TIMEOUT);
- prl_set_rev(port, TCPCI_MSG_SOP_PRIME, PD_REV20);
- }
-
- /*
- * 6.6.15 DiscoverIdentityTimer
- *
- * No more than nDiscoverIdentityCount Discover Identity Messages
- * without a GoodCRC Message response Shall be sent. If no GoodCRC
- * Message response is received after nDiscoverIdentityCount Discover
- * Identity Command requests have been sent by a Port, the Port Shall
- * Not send any further SOP’/SOP’’ Messages.
- */
- if (pe[port].discover_identity_counter >= N_DISCOVER_IDENTITY_COUNT)
- pd_set_identity_discovery(port, pe[port].tx_type,
- PD_DISC_FAIL);
- else if (pe[port].discover_identity_counter ==
- N_DISCOVER_IDENTITY_PD3_0_LIMIT)
- /*
- * Downgrade to PD 2.0 if the partner hasn't replied before
- * all retries are exhausted in case the cable is
- * non-compliant about GoodCRC-ing higher revisions
- */
- prl_set_rev(port, TCPCI_MSG_SOP_PRIME, PD_REV20);
-
- /*
- * Set discover identity timer unless BUSY case already did so.
- */
- if (pd_get_identity_discovery(port, pe[port].tx_type) == PD_DISC_NEEDED
- && pd_timer_is_expired(port, PE_TIMER_DISCOVER_IDENTITY)) {
- /*
- * The tDiscoverIdentity timer is used during an explicit
- * contract when discovering whether a cable is PD capable.
- *
- * Pre-contract, slow the rate Discover Identity commands are
- * sent. This permits operation with captive cable devices that
- * power the SOP' responder from VBUS instead of VCONN.
- */
- pd_timer_enable(port, PE_TIMER_DISCOVER_IDENTITY,
- pe_is_explicit_contract(port)
- ? PD_T_DISCOVER_IDENTITY
- : PE_T_DISCOVER_IDENTITY_NO_CONTRACT);
- }
-
- /* Do not attempt further discovery if identity discovery failed. */
- if (pd_get_identity_discovery(port, pe[port].tx_type) == PD_DISC_FAIL) {
- pd_set_svids_discovery(port, pe[port].tx_type, PD_DISC_FAIL);
- pd_notify_event(port, pe[port].tx_type == TCPCI_MSG_SOP ?
- PD_STATUS_EVENT_SOP_DISC_DONE :
- PD_STATUS_EVENT_SOP_PRIME_DISC_DONE);
- }
-}
-
-/**
- * PE_INIT_PORT_VDM_Identity_Request
- *
- * Specific to SOP requests, as cables require additions for the discover
- * identity counter, must tolerate not receiving a GoodCRC, and need to set the
- * cable revision based on response.
- * pe[port].tx_type must be set (to SOP) prior to entry.
- */
-static void pe_init_port_vdm_identity_request_entry(int port)
-{
- uint32_t *msg = (uint32_t *)tx_emsg[port].buf;
-
- print_current_state(port);
-
- msg[0] = VDO(USB_SID_PD, 1,
- VDO_SVDM_VERS(pd_get_vdo_ver(port, pe[port].tx_type)) |
- CMD_DISCOVER_IDENT);
- tx_emsg[port].len = sizeof(uint32_t);
-
- send_data_msg(port, pe[port].tx_type, PD_DATA_VENDOR_DEF);
-
- /*
- * Valid DiscoverIdentity responses should have at least 4 objects
- * (header, ID header, Cert Stat, Product VDO).
- */
- pe[port].vdm_ack_min_data_objects = 4;
-}
-
-static void pe_init_port_vdm_identity_request_run(int port)
-{
- switch (parse_vdm_response_common(port)) {
- case VDM_RESULT_WAITING:
- /* If common code didn't parse a message, continue waiting. */
- return;
- case VDM_RESULT_NO_ACTION:
- /*
- * If the received message doesn't change the discovery state,
- * there is nothing to do but return to the previous ready
- * state.
- */
- break;
- case VDM_RESULT_ACK: {
- /* Retrieve the message information. */
- uint32_t *payload = (uint32_t *) rx_emsg[port].buf;
- int sop = PD_HEADER_GET_SOP(rx_emsg[port].header);
- uint8_t cnt = PD_HEADER_CNT(rx_emsg[port].header);
-
- /* PE_INIT_PORT_VDM_Identity_ACKed embedded here */
- dfp_consume_identity(port, sop, cnt, payload);
-
- break;
- }
- case VDM_RESULT_NAK:
- /* PE_INIT_PORT_VDM_IDENTITY_NAKed embedded here */
- pd_set_identity_discovery(port, pe[port].tx_type, PD_DISC_FAIL);
- break;
- }
-
- /* Return to calling state (PE_{SRC,SNK}_Ready) */
- set_state_pe(port, get_last_state_pe(port));
-}
-
-static void pe_init_port_vdm_identity_request_exit(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_VDM_REQUEST_TIMEOUT)) {
- PE_CLR_FLAG(port, PE_FLAGS_VDM_REQUEST_TIMEOUT);
- /*
- * Mark failure to respond as discovery failure.
- *
- * For PD 2.0 partners (6.10.3 Applicability of Structured VDM
- * Commands Note 3):
- *
- * If Structured VDMs are not supported, a Structured VDM
- * Command received by a DFP or UFP Shall be Ignored.
- */
- pd_set_identity_discovery(port, pe[port].tx_type, PD_DISC_FAIL);
- }
-
- /* Do not attempt further discovery if identity discovery failed. */
- if (pd_get_identity_discovery(port, pe[port].tx_type) == PD_DISC_FAIL) {
- pd_set_svids_discovery(port, pe[port].tx_type, PD_DISC_FAIL);
- pd_notify_event(port, pe[port].tx_type == TCPCI_MSG_SOP ?
- PD_STATUS_EVENT_SOP_DISC_DONE :
- PD_STATUS_EVENT_SOP_PRIME_DISC_DONE);
- }
-}
-
-/**
- * PE_INIT_VDM_SVIDs_Request
- *
- * Used for SOP and SOP' requests, selected by pe[port].tx_type prior to entry.
- */
-static void pe_init_vdm_svids_request_entry(int port)
-{
- uint32_t *msg = (uint32_t *)tx_emsg[port].buf;
-
- print_current_state(port);
-
- if (pe[port].tx_type == TCPCI_MSG_SOP_PRIME &&
- !pe_can_send_sop_prime(port)) {
- /*
- * The parent state already tried to enable SOP' traffic. If it
- * is still disabled, there's nothing left to try.
- */
- pd_set_svids_discovery(port, pe[port].tx_type, PD_DISC_FAIL);
- set_state_pe(port, get_last_state_pe(port));
- return;
- }
-
- msg[0] = VDO(USB_SID_PD, 1,
- VDO_SVDM_VERS(pd_get_vdo_ver(port, pe[port].tx_type)) |
- CMD_DISCOVER_SVID);
- tx_emsg[port].len = sizeof(uint32_t);
-
- send_data_msg(port, pe[port].tx_type, PD_DATA_VENDOR_DEF);
-
- /*
- * Valid Discover SVIDs ACKs should have at least 2 objects (VDM header
- * and at least 1 SVID VDO).
- */
- pe[port].vdm_ack_min_data_objects = 2;
-}
-
-static void pe_init_vdm_svids_request_run(int port)
-{
- switch (parse_vdm_response_common(port)) {
- case VDM_RESULT_WAITING:
- /* If common code didn't parse a message, continue waiting. */
- return;
- case VDM_RESULT_NO_ACTION:
- /*
- * If the received message doesn't change the discovery state,
- * there is nothing to do but return to the previous ready
- * state.
- */
- break;
- case VDM_RESULT_ACK: {
- /* Retrieve the message information. */
- uint32_t *payload = (uint32_t *) rx_emsg[port].buf;
- int sop = PD_HEADER_GET_SOP(rx_emsg[port].header);
- uint8_t cnt = PD_HEADER_CNT(rx_emsg[port].header);
-
- /* PE_INIT_VDM_SVIDs_ACKed embedded here */
- dfp_consume_svids(port, sop, cnt, payload);
- break;
- }
- case VDM_RESULT_NAK:
- /* PE_INIT_VDM_SVIDs_NAKed embedded here */
- pd_set_svids_discovery(port, pe[port].tx_type, PD_DISC_FAIL);
- break;
- }
-
- /* Return to calling state (PE_{SRC,SNK}_Ready) */
- set_state_pe(port, get_last_state_pe(port));
-}
-
-static void pe_init_vdm_svids_request_exit(int port)
-{
- if (PE_CHK_FLAG(port, PE_FLAGS_VDM_REQUEST_TIMEOUT)) {
- PE_CLR_FLAG(port, PE_FLAGS_VDM_REQUEST_TIMEOUT);
- /*
- * Mark failure to respond as discovery failure.
- *
- * For PD 2.0 partners (6.10.3 Applicability of Structured VDM
- * Commands Note 3):
- *
- * If Structured VDMs are not supported, a Structured VDM
- * Command received by a DFP or UFP Shall be Ignored.
- */
- pd_set_svids_discovery(port, pe[port].tx_type, PD_DISC_FAIL);
- }
-
- /* If SVID discovery failed, discovery is done at this point */
- if (pd_get_svids_discovery(port, pe[port].tx_type) == PD_DISC_FAIL)
- pd_notify_event(port, pe[port].tx_type == TCPCI_MSG_SOP ?
- PD_STATUS_EVENT_SOP_DISC_DONE :
- PD_STATUS_EVENT_SOP_PRIME_DISC_DONE);
-}
-
-/**
- * PE_INIT_VDM_Modes_Request
- *
- * Used for SOP and SOP' requests, selected by pe[port].tx_type prior to entry.
- */
-static void pe_init_vdm_modes_request_entry(int port)
-{
- uint32_t *msg = (uint32_t *)tx_emsg[port].buf;
- const struct svid_mode_data *mode_data =
- pd_get_next_mode(port, pe[port].tx_type);
- uint16_t svid;
- /*
- * The caller should have checked that there was something to discover
- * before entering this state.
- */
- assert(mode_data);
- assert(mode_data->discovery == PD_DISC_NEEDED);
- svid = mode_data->svid;
-
- print_current_state(port);
-
- if (pe[port].tx_type == TCPCI_MSG_SOP_PRIME &&
- !pe_can_send_sop_prime(port)) {
- /*
- * The parent state already tried to enable SOP' traffic. If it
- * is still disabled, there's nothing left to try.
- */
- pd_set_modes_discovery(port, pe[port].tx_type, svid,
- PD_DISC_FAIL);
- set_state_pe(port, get_last_state_pe(port));
- return;
- }
-
- msg[0] = VDO((uint16_t) svid, 1,
- VDO_SVDM_VERS(pd_get_vdo_ver(port, pe[port].tx_type)) |
- CMD_DISCOVER_MODES);
- tx_emsg[port].len = sizeof(uint32_t);
-
- send_data_msg(port, pe[port].tx_type, PD_DATA_VENDOR_DEF);
-
- /*
- * Valid Discover Modes responses should have at least 2 objects (VDM
- * header and at least 1 mode VDO).
- */
- pe[port].vdm_ack_min_data_objects = 2;
-}
-
-static void pe_init_vdm_modes_request_run(int port)
-{
- const struct svid_mode_data *mode_data;
- uint16_t requested_svid;
-
- mode_data = pd_get_next_mode(port, pe[port].tx_type);
-
- assert(mode_data);
- assert(mode_data->discovery == PD_DISC_NEEDED);
- requested_svid = mode_data->svid;
-
- switch (parse_vdm_response_common(port)) {
- case VDM_RESULT_WAITING:
- /* If common code didn't parse a message, continue waiting. */
- return;
- case VDM_RESULT_NO_ACTION:
- /*
- * If the received message doesn't change the discovery state,
- * there is nothing to do but return to the previous ready
- * state.
- */
- break;
- case VDM_RESULT_ACK: {
- /* Retrieve the message information. */
- uint32_t *payload = (uint32_t *) rx_emsg[port].buf;
- int sop = PD_HEADER_GET_SOP(rx_emsg[port].header);
- uint8_t cnt = PD_HEADER_CNT(rx_emsg[port].header);
- uint16_t response_svid = (uint16_t) PD_VDO_VID(payload[0]);
-
- /*
- * Accept ACK if the request and response SVIDs are equal;
- * otherwise, treat this as a NAK of the request SVID.
- *
- * TODO(b:169242812): support valid mode checking in
- * dfp_consume_modes.
- */
- if (requested_svid == response_svid) {
- /* PE_INIT_VDM_Modes_ACKed embedded here */
- dfp_consume_modes(port, sop, cnt, payload);
- break;
- }
- }
- /* Fall Through */
- case VDM_RESULT_NAK:
- /* PE_INIT_VDM_Modes_NAKed embedded here */
- pd_set_modes_discovery(port, pe[port].tx_type, requested_svid,
- PD_DISC_FAIL);
- break;
- }
-
- /* Return to calling state (PE_{SRC,SNK}_Ready) */
- set_state_pe(port, get_last_state_pe(port));
-}
-
-static void pe_init_vdm_modes_request_exit(int port)
-{
- if (pd_get_modes_discovery(port, pe[port].tx_type) != PD_DISC_NEEDED)
- /* Mode discovery done, notify the AP */
- pd_notify_event(port, pe[port].tx_type == TCPCI_MSG_SOP ?
- PD_STATUS_EVENT_SOP_DISC_DONE :
- PD_STATUS_EVENT_SOP_PRIME_DISC_DONE);
-
-}
-
-/**
- * PE_VDM_REQUEST_DPM
- *
- * Makes a VDM request with contents and SOP* type previously set up by the DPM.
- */
-
-static void pe_vdm_request_dpm_entry(int port)
-{
- print_current_state(port);
-
- if ((pe[port].tx_type == TCPCI_MSG_SOP_PRIME ||
- pe[port].tx_type == TCPCI_MSG_SOP_PRIME_PRIME) &&
- !pe_can_send_sop_prime(port)) {
- /*
- * The parent state already tried to enable SOP' traffic. If it
- * is still disabled, there's nothing left to try.
- */
- dpm_vdm_naked(port, pe[port].tx_type,
- PD_VDO_VID(pe[port].vdm_data[0]),
- PD_VDO_CMD(pe[port].vdm_data[0]));
- set_state_pe(port, get_last_state_pe(port));
- return;
- }
-
- /* Copy Vendor Data Objects (VDOs) into message buffer */
- if (pe[port].vdm_cnt > 0) {
- /* Copy data after header */
- memcpy(&tx_emsg[port].buf,
- (uint8_t *)pe[port].vdm_data,
- pe[port].vdm_cnt * 4);
- /* Update len with the number of VDO bytes */
- tx_emsg[port].len = pe[port].vdm_cnt * 4;
- }
-
- /*
- * Clear the VDM nak'ed flag so that each request is
- * treated separately (NAKs are handled by the
- * DPM layer). Otherwise previous NAKs received will
- * cause the state to exit early.
- */
- PE_CLR_FLAG(port, PE_FLAGS_VDM_REQUEST_NAKED);
- send_data_msg(port, pe[port].tx_type, PD_DATA_VENDOR_DEF);
-
- /*
- * In general, valid VDM ACKs must have a VDM header. Other than that,
- * ACKs must be validated based on the command and SVID.
- */
- pe[port].vdm_ack_min_data_objects = 1;
-}
-
-static void pe_vdm_request_dpm_run(int port)
-{
- uint32_t vdm_hdr;
-
- switch (parse_vdm_response_common(port)) {
- case VDM_RESULT_WAITING:
- /*
- * USB-PD 3.0 Rev 1.1 - 6.4.4.2.5
- * Structured VDM command consists of a command request and a
- * command response (ACK, NAK, or BUSY). An exception is made
- * for the Attention command which shall have no response.
- *
- * Since Attention commands do not have an expected reply,
- * the SVDM command is complete once the Attention command
- * transmit is complete.
- */
- vdm_hdr = pe[port].vdm_data[0];
- if(PD_VDO_SVDM(vdm_hdr) &&
- (PD_VDO_CMD(vdm_hdr) == CMD_ATTENTION)) {
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- break;
- }
- }
- /*
- * If common code didn't parse a message, and the VDM
- * just sent was not an Attention message, then continue
- * waiting.
- */
- return;
- case VDM_RESULT_NO_ACTION:
- /*
- * If the received message doesn't change the discovery state,
- * there is nothing to do but return to the previous ready
- * state. This includes Attention commands which have no
- * expected SVDM response.
- */
- break;
- case VDM_RESULT_ACK: {
- /* Retrieve the message information. */
- uint32_t *payload = (uint32_t *) rx_emsg[port].buf;
- int sop = PD_HEADER_GET_SOP(rx_emsg[port].header);
- uint8_t cnt = PD_HEADER_CNT(rx_emsg[port].header);
- uint16_t svid = PD_VDO_VID(payload[0]);
- uint8_t vdm_cmd = PD_VDO_CMD(payload[0]);
-
- /*
- * PE initiator VDM-ACKed state for requested VDM, like
- * PE_INIT_VDM_FOO_ACKed, embedded here.
- */
- dpm_vdm_acked(port, sop, cnt, payload);
-
- if (sop == TCPCI_MSG_SOP && svid == USB_SID_DISPLAYPORT &&
- vdm_cmd == CMD_DP_CONFIG) {
- PE_SET_FLAG(port, PE_FLAGS_VDM_SETUP_DONE);
- }
- break;
- }
- case VDM_RESULT_NAK:
- /*
- * PE initiator VDM-NAKed state for requested VDM, like
- * PE_INIT_VDM_FOO_NAKed, embedded here.
- */
- PE_SET_FLAG(port, PE_FLAGS_VDM_SETUP_DONE);
-
- /*
- * Because Not Supported messages or response timeouts are
- * treated as NAKs, there may not be a NAK message to parse.
- * Extract the needed information from the sent VDM.
- */
- dpm_vdm_naked(port, pe[port].tx_type,
- PD_VDO_VID(pe[port].vdm_data[0]),
- PD_VDO_CMD(pe[port].vdm_data[0]));
- break;
- }
-
- /* Return to calling state (PE_{SRC,SNK}_Ready) */
- set_state_pe(port, get_last_state_pe(port));
-}
-
-static void pe_vdm_request_dpm_exit(int port)
-{
- /*
- * Force Tx type to be reset before reentering a VDM state, unless the
- * current VDM request will be resumed.
- */
- if (!PE_CHK_FLAG(port, PE_FLAGS_VDM_REQUEST_CONTINUE))
- pe[port].tx_type = TCPCI_MSG_INVALID;
-}
-
-/**
- * PE_VDM_Response
- */
-static void pe_vdm_response_entry(int port)
-{
- int vdo_len = 0;
- uint32_t *rx_payload;
- uint32_t *tx_payload;
- uint8_t vdo_cmd;
- svdm_rsp_func func = NULL;
-
- print_current_state(port);
-
- /* This is an Interruptible AMS */
- PE_SET_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
-
- /* Get the message */
- rx_payload = (uint32_t *)rx_emsg[port].buf;
-
- /* Extract VDM command from the VDM header */
- vdo_cmd = PD_VDO_CMD(rx_payload[0]);
- /* This must be a command request to proceed further */
- if (PD_VDO_CMDT(rx_payload[0]) != CMDT_INIT) {
- CPRINTF("ERR:CMDT:%d:%d\n", PD_VDO_CMDT(rx_payload[0]),
- vdo_cmd);
-
- pe_set_ready_state(port);
- return;
- }
-
- tx_payload = (uint32_t *)tx_emsg[port].buf;
- /*
- * Designed in TCPMv1, svdm_response functions use same
- * buffer to take received data and overwrite with response
- * data. To work with this interface, here copy rx data to
- * tx buffer and pass tx_payload to func.
- * TODO(b/166455363): change the interface to pass both rx
- * and tx buffer.
- *
- * The SVDM header is dependent on both VDM command request being
- * replied to and the result of response function. The SVDM command
- * message is copied into tx_payload. tx_payload[0] is the VDM header
- * for the response message. The SVDM response function takes the role
- * of the DPM layer and will indicate the response type (ACK/NAK/BUSY)
- * by its return value (vdo_len)
- * vdo_len > 0 --> ACK
- * vdo_len == 0 --> NAK
- * vdo_len < 0 --> BUSY
- */
- memcpy(tx_payload, rx_payload, PD_HEADER_CNT(rx_emsg[port].header) * 4);
- /*
- * Clear fields in SVDM response message that will be set based on the
- * result of the svdm response function.
- */
- tx_payload[0] &= ~VDO_CMDT_MASK;
- tx_payload[0] &= ~VDO_SVDM_VERS(0x3);
-
- /* Add SVDM structured version being used */
- tx_payload[0] |= VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP));
-
- /* Use VDM command to select the response handler function */
- switch (vdo_cmd) {
- case CMD_DISCOVER_IDENT:
- func = svdm_rsp.identity;
- break;
- case CMD_DISCOVER_SVID:
- func = svdm_rsp.svids;
- break;
- case CMD_DISCOVER_MODES:
- func = svdm_rsp.modes;
- break;
- case CMD_ENTER_MODE:
- func = svdm_rsp.enter_mode;
- break;
- case CMD_DP_STATUS:
- if (svdm_rsp.amode)
- func = svdm_rsp.amode->status;
- break;
- case CMD_DP_CONFIG:
- if (svdm_rsp.amode)
- func = svdm_rsp.amode->config;
- break;
- case CMD_EXIT_MODE:
- func = svdm_rsp.exit_mode;
- break;
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- case CMD_ATTENTION:
- /*
- * attention is only SVDM with no response
- * (just goodCRC) return zero here.
- */
- dfp_consume_attention(port, rx_payload);
- pe_set_ready_state(port);
- return;
-#endif
- default:
- CPRINTF("VDO ERR:CMD:%d\n", vdo_cmd);
- }
-
- /*
- * If the port partner is PD_REV20 and our data role is DFP, we must
- * reply to any SVDM command with a NAK. If the SVDM was an Attention
- * command, it does not have a response, and exits the function above.
- */
- if (func && (prl_get_rev(port, TCPCI_MSG_SOP) != PD_REV20 ||
- pe[port].data_role == PD_ROLE_UFP)) {
- /*
- * Execute SVDM response function selected above and set the
- * correct response type in the VDM header.
- */
- vdo_len = func(port, tx_payload);
- if (vdo_len > 0) {
- tx_payload[0] |= VDO_CMDT(CMDT_RSP_ACK);
- /*
- * If command response is an ACK and if the command was
- * either enter/exit mode, then update the PE modal flag
- * accordingly.
- */
- if (vdo_cmd == CMD_ENTER_MODE)
- PE_SET_FLAG(port, PE_FLAGS_MODAL_OPERATION);
- if (vdo_cmd == CMD_EXIT_MODE)
- PE_CLR_FLAG(port, PE_FLAGS_MODAL_OPERATION);
- } else if (!vdo_len) {
- tx_payload[0] |= VDO_CMDT(CMDT_RSP_NAK);
- vdo_len = 1;
- } else {
- tx_payload[0] |= VDO_CMDT(CMDT_RSP_BUSY);
- vdo_len = 1;
- }
- } else {
- /*
- * Received at VDM command which is not supported. PD 2.0 may
- * NAK or ignore the message (see TD.PD.VNDI.E1. VDM Identity
- * steps), but PD 3.0 must send Not_Supported (PD 3.0 Ver 2.0 +
- * ECNs 2020-12-10 Table 6-64 Response to an incoming
- * VDM or TD.PD.VNDI3.E3 VDM Identity steps)
- */
- if (prl_get_rev(port, TCPCI_MSG_SOP) == PD_REV30) {
- set_state_pe(port, PE_SEND_NOT_SUPPORTED);
- return;
- }
- tx_payload[0] |= VDO_CMDT(CMDT_RSP_NAK);
- vdo_len = 1;
- }
-
- /* Send response message. Note len is in bytes, not VDO objects */
- tx_emsg[port].len = (vdo_len * sizeof(uint32_t));
- send_data_msg(port, TCPCI_MSG_SOP, PD_DATA_VENDOR_DEF);
-}
-
-static void pe_vdm_response_run(int port)
-{
- /*
- * This state waits for a VDM response message to be sent. Return to the
- * ready state once the message has been sent, a protocol error was
- * detected, or if the VDM response msg was discarded based on being
- * interrupted by another rx message. Since VDM sequences are AMS
- * interruptible, there is no need to soft reset regardless of exit
- * reason.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE) ||
- PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR) ||
- PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) {
-
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE |
- PE_FLAGS_PROTOCOL_ERROR |
- PE_FLAGS_MSG_DISCARDED);
-
- pe_set_ready_state(port);
- }
-}
-
-static void pe_vdm_response_exit(int port)
-{
- PE_CLR_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
-}
-
-/**
- * PE_DEU_SEND_ENTER_USB
- */
-static void pe_enter_usb_entry(int port)
-{
- uint32_t usb4_payload;
-
- print_current_state(port);
-
- if (!IS_ENABLED(CONFIG_USB_PD_USB4)) {
- pe_set_ready_state(port);
- return;
- }
-
- /* Port is already in USB4 mode, do not send enter USB message again */
- if (enter_usb_entry_is_done(port)) {
- pe_set_ready_state(port);
- return;
- }
-
- if ((pe[port].tx_type == TCPCI_MSG_SOP_PRIME ||
- pe[port].tx_type == TCPCI_MSG_SOP_PRIME_PRIME) &&
- !tc_is_vconn_src(port)) {
- if (port_try_vconn_swap(port))
- return;
- }
-
- pe[port].tx_type = TCPCI_MSG_SOP;
- usb4_payload = enter_usb_setup_next_msg(port, &pe[port].tx_type);
-
- if (!usb4_payload) {
- enter_usb_failed(port);
- pe_set_ready_state(port);
- return;
- }
-
- tx_emsg[port].len = sizeof(usb4_payload);
-
- memcpy(tx_emsg[port].buf, &usb4_payload, tx_emsg[port].len);
- send_data_msg(port, pe[port].tx_type, PD_DATA_ENTER_USB);
- pe_sender_response_msg_entry(port);
-}
-
-static void pe_enter_usb_run(int port)
-{
- enum pe_msg_check msg_check;
-
- if (!IS_ENABLED(CONFIG_USB_PD_USB4)) {
- pe_set_ready_state(port);
- return;
- }
-
- /*
- * Check the state of the message sent
- */
- 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;
- }
-
- if (pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE)) {
- pe_set_ready_state(port);
- enter_usb_failed(port);
- return;
- }
-
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- int cnt = PD_HEADER_CNT(rx_emsg[port].header);
- int type = PD_HEADER_TYPE(rx_emsg[port].header);
- int sop = PD_HEADER_GET_SOP(rx_emsg[port].header);
-
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- /* Only look at control messages */
- if (cnt == 0) {
- /* Accept message received */
- if (type == PD_CTRL_ACCEPT) {
- enter_usb_accepted(port, sop);
- } else if (type == PD_CTRL_REJECT) {
- enter_usb_rejected(port, sop);
- } else {
- /*
- * Unexpected control message received.
- * Send Soft Reset.
- */
- pe_send_soft_reset(port, sop);
- return;
- }
- } else {
- /* Unexpected data message received. Send Soft reset */
- pe_send_soft_reset(port, sop);
- return;
- }
- pe_set_ready_state(port);
- }
-}
-
-static void pe_enter_usb_exit(int port)
-{
- pe_sender_response_msg_exit(port);
-}
-
-#ifdef CONFIG_USBC_VCONN
-/*
- * PE_VCS_Evaluate_Swap
- */
-static void pe_vcs_evaluate_swap_entry(int port)
-{
- print_current_state(port);
-
- /*
- * Request the DPM for an evaluation of the VCONN Swap request.
- * Note: Ports that are presently the VCONN Source must always
- * accept a VCONN
- */
-
- /*
- * Transition to the PE_VCS_Accept_Swap state when:
- * 1) The Device Policy Manager indicates that a VCONN Swap is ok.
- *
- * Transition to the PE_VCS_Reject_Swap state when:
- * 1) Port is not presently the VCONN Source and
- * 2) The DPM indicates that a VCONN Swap is not ok or
- * 3) The DPM indicates that a VCONN Swap cannot be done at this time.
- */
-
- /* DPM rejects a VCONN Swap and port is not a VCONN source*/
- if (!tc_check_vconn_swap(port) && tc_is_vconn_src(port) < 1) {
- /* NOTE: PE_VCS_Reject_Swap State embedded here */
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_REJECT);
- }
- /* Port is not ready to perform a VCONN swap */
- else if (tc_is_vconn_src(port) < 0) {
- /* NOTE: PE_VCS_Reject_Swap State embedded here */
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_WAIT);
- }
- /* Port is ready to perform a VCONN swap */
- else {
- /* NOTE: PE_VCS_Accept_Swap State embedded here */
- PE_SET_FLAG(port, PE_FLAGS_ACCEPT);
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_ACCEPT);
- }
-}
-
-static void pe_vcs_evaluate_swap_run(int port)
-{
- /* Wait for ACCEPT, WAIT or Reject message to send. */
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
-
- if (PE_CHK_FLAG(port, PE_FLAGS_ACCEPT)) {
- PE_CLR_FLAG(port, PE_FLAGS_ACCEPT);
- /* Accept Message sent and Presently VCONN Source */
- if (tc_is_vconn_src(port))
- set_state_pe(port, PE_VCS_WAIT_FOR_VCONN_SWAP);
- /* Accept Message sent and Not presently VCONN Source */
- else
- set_state_pe(port, PE_VCS_TURN_ON_VCONN_SWAP);
- } else {
- /*
- * Message sent. Transition back to PE_SRC_Ready or
- * PE_SINK_Ready
- */
- pe_set_ready_state(port);
- }
- return;
- }
-
- if (pe_check_outgoing_discard(port))
- return;
-}
-
-/*
- * PE_VCS_Send_Swap
- */
-static void pe_vcs_send_swap_entry(int port)
-{
- print_current_state(port);
-
- /* Send a VCONN_Swap Message */
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_VCONN_SWAP);
- pe_sender_response_msg_entry(port);
-}
-
-static void pe_vcs_send_swap_run(int port)
-{
- uint8_t type;
- uint8_t cnt;
- enum tcpci_msg_type sop;
- enum pe_msg_check msg_check;
-
- /*
- * Check the state of the message sent
- */
- msg_check = pe_sender_response_msg_run(port);
-
- if ((msg_check & PE_MSG_SENT) &&
- PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- /* Increment once message has successfully sent */
- pe[port].vconn_swap_counter++;
-
- type = PD_HEADER_TYPE(rx_emsg[port].header);
- cnt = PD_HEADER_CNT(rx_emsg[port].header);
- sop = PD_HEADER_GET_SOP(rx_emsg[port].header);
-
- /* Only look at control messages */
- if (cnt == 0) {
- /*
- * Transition to the PE_VCS_Wait_For_VCONN state when:
- * 1) Accept Message Received and
- * 2) The Port is presently the VCONN Source.
- *
- * Transition to the PE_VCS_Turn_On_VCONN state when:
- * 1) Accept Message Received and
- * 2) The Port is not presently the VCONN Source.
- */
- if (type == PD_CTRL_ACCEPT) {
- if (tc_is_vconn_src(port)) {
- set_state_pe(port,
- PE_VCS_WAIT_FOR_VCONN_SWAP);
- } else {
- set_state_pe(port,
- PE_VCS_TURN_ON_VCONN_SWAP);
- }
- return;
- }
- /*
- * Transition back to either the PE_SRC_Ready or
- * PE_SNK_Ready state when:
- * 2) Reject message is received or
- * 3) Wait message Received.
- */
- if (type == PD_CTRL_REJECT || type == PD_CTRL_WAIT) {
- pe_set_ready_state(port);
- return;
- }
-
- /*
- * The Policy Engine May transition to the
- * PE_VCS_Force_Vconn state when:
- * - A Not_Supported Message is received and
- * - The Port is not presently the VCONN Source
- */
- if (type == PD_CTRL_NOT_SUPPORTED) {
- if (IS_ENABLED(CONFIG_USB_PD_REV30) &&
- !tc_is_vconn_src(port))
- set_state_pe(port, PE_VCS_FORCE_VCONN);
- else
- pe_set_ready_state(port);
- return;
- }
- }
- /*
- * Unexpected Message Received, send soft reset with SOP* of
- * incoming message.
- */
- pe_send_soft_reset(port, sop);
- return;
- }
-
- /*
- * Transition back to either the PE_SRC_Ready or
- * PE_SNK_Ready state when:
- * 1) SenderResponseTimer Timeout
- * 2) Message was discarded.
- */
- if ((msg_check & PE_MSG_DISCARDED) ||
- pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE))
- pe_set_ready_state(port);
-}
-
-static void pe_vcs_send_swap_exit(int port)
-{
- pe_sender_response_msg_exit(port);
-}
-
-/*
- * PE_VCS_Wait_for_VCONN_Swap
- */
-static void pe_vcs_wait_for_vconn_swap_entry(int port)
-{
- print_current_state(port);
-
- /* Start the VCONNOnTimer */
- pd_timer_enable(port, PE_TIMER_VCONN_ON, PD_T_VCONN_SOURCE_ON);
-
- /*
- * The USB PD 3.0 spec indicates that the initial VCONN source
- * shall cease sourcing VCONN within tVCONNSourceOff (25ms)
- * after receiving the PS_RDY message. However, some partners
- * begin sending SOP' messages only 1 ms after sending PS_RDY
- * during VCONN swap.
- *
- * Preemptively disable receipt of SOP' and SOP'' messages while
- * we wait for PS_RDY so we don't attempt to process messages
- * directed at the cable.
- *
- * We continue to source VCONN while we wait as required by the
- * spec.
- */
- tcpm_sop_prime_enable(port, false);
-}
-
-static void pe_vcs_wait_for_vconn_swap_run(int port)
-{
- /*
- * Transition to the PE_VCS_Turn_Off_VCONN state when:
- * 1) A PS_RDY Message is received.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- /*
- * PS_RDY message received
- *
- * Note: intentionally leave the receive flag set to indicate
- * our route on exit when PS_RDY is received.
- */
- if ((PD_HEADER_CNT(rx_emsg[port].header) == 0) &&
- (PD_HEADER_EXT(rx_emsg[port].header) == 0) &&
- (PD_HEADER_TYPE(rx_emsg[port].header) == PD_CTRL_PS_RDY)) {
- set_state_pe(port, PE_VCS_TURN_OFF_VCONN_SWAP);
- return;
- } else {
- /*
- * Unexpected message received - reset with the SOP* of
- * the incoming message.
- */
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
- pe_send_soft_reset(port,
- PD_HEADER_GET_SOP(rx_emsg[port].header));
- return;
- }
- }
-
- /*
- * Transition to either the PE_SRC_Hard_Reset or
- * PE_SNK_Hard_Reset state when:
- * 1) The VCONNOnTimer times out.
- */
- if (pd_timer_is_expired(port, PE_TIMER_VCONN_ON)) {
- if (pe[port].power_role == PD_ROLE_SOURCE)
- set_state_pe(port, PE_SRC_HARD_RESET);
- else
- set_state_pe(port, PE_SNK_HARD_RESET);
- }
-}
-
-static void pe_vcs_wait_for_vconn_swap_exit(int port)
-{
- /*
- * If we exited without getting PS_RDY, re-enable SOP' messaging since
- * we are still the Vconn source.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED))
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
- else
- tcpm_sop_prime_enable(port, true);
-
- pd_timer_disable(port, PE_TIMER_VCONN_ON);
-}
-
-/*
- * PE_VCS_Turn_On_VCONN_Swap
- */
-static void pe_vcs_turn_on_vconn_swap_entry(int port)
-{
- print_current_state(port);
-
- /* Request DPM to turn on VCONN */
- pd_request_vconn_swap_on(port);
-}
-
-static void pe_vcs_turn_on_vconn_swap_run(int port)
-{
-
- /*
- * Transition to the PE_VCS_Send_Ps_Rdy state when:
- * 1) The Port’s VCONN is on.
- */
- if (pd_timer_is_disabled(port, PE_TIMER_TIMEOUT) &&
- PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE);
- pd_timer_enable(port, PE_TIMER_TIMEOUT,
- CONFIG_USBC_VCONN_SWAP_DELAY_US);
- }
-
- if (pd_timer_is_expired(port, PE_TIMER_TIMEOUT))
- set_state_pe(port, PE_VCS_SEND_PS_RDY_SWAP);
-}
-
-static void pe_vcs_turn_on_vconn_swap_exit(int port)
-{
- pd_timer_disable(port, PE_TIMER_TIMEOUT);
-}
-
-/*
- * PE_VCS_Turn_Off_VCONN_Swap
- */
-static void pe_vcs_turn_off_vconn_swap_entry(int port)
-{
- print_current_state(port);
-
- /* Request DPM to turn off VCONN */
- pd_request_vconn_swap_off(port);
-}
-
-static void pe_vcs_turn_off_vconn_swap_run(int port)
-{
- /* Wait for VCONN to turn off */
- if (PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE);
-
- /*
- * A VCONN Swap Shall reset the DiscoverIdentityCounter
- * to zero
- */
- pe[port].discover_identity_counter = 0;
- pe[port].dr_swap_attempt_counter = 0;
-
- pe_set_ready_state(port);
- return;
- }
-}
-
-/*
- * PE_VCS_Send_PS_Rdy_Swap
- */
-static void pe_vcs_send_ps_rdy_swap_entry(int port)
-{
- print_current_state(port);
-
- /* Check for any interruptions to this non-interruptible AMS */
- if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- enum tcpci_msg_type sop =
- PD_HEADER_GET_SOP(rx_emsg[port].header);
-
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- /* Soft reset with the SOP* of the incoming message */
- pe_send_soft_reset(port, sop);
- return;
- }
-
- /* Send a PS_RDY Message */
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_PS_RDY);
-}
-
-static void pe_vcs_send_ps_rdy_swap_run(int port)
-{
- /*
- * After a VCONN Swap the VCONN Source needs to reset
- * the Cable Plug’s Protocol Layer in order to ensure
- * MessageID synchronization.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- /*
- * A VCONN Swap Shall reset the
- * DiscoverIdentityCounter to zero
- */
- pe[port].discover_identity_counter = 0;
- pe[port].dr_swap_attempt_counter = 0;
-
- /* A SOP' soft reset is required after VCONN swap */
- pd_dpm_request(port, DPM_REQUEST_SOP_PRIME_SOFT_RESET_SEND);
- pe_set_ready_state(port);
- }
-
- if (pe_check_outgoing_discard(port))
- return;
-
- if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
- PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
- /* PS_RDY didn't send, soft reset */
- pe_send_soft_reset(port, TCPCI_MSG_SOP);
- }
-}
-
-/*
- * PE_VCS_Force_Vconn
- */
-__maybe_unused static void pe_vcs_force_vconn_entry(int port)
-{
- print_current_state(port);
-
- /* Request DPM to turn on VCONN */
- pd_request_vconn_swap_on(port);
-}
-
-__maybe_unused static void pe_vcs_force_vconn_run(int port)
-{
- /*
- * The Policy Engine Shall transition back to either the PE_SRC_Ready
- * or PE_SNK_Ready state when:
- * 1) The Port’s VCONN is on.
- *
- * Note we'll wait CONFIG_USBC_VCONN_SWAP_DELAY_US, as defined by the
- * board, to ensure Vconn is on.
- */
- if (pd_timer_is_disabled(port, PE_TIMER_TIMEOUT) &&
- PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE);
- pd_timer_enable(port, PE_TIMER_TIMEOUT,
- CONFIG_USBC_VCONN_SWAP_DELAY_US);
- }
-
- if (pd_timer_is_expired(port, PE_TIMER_TIMEOUT)) {
- /*
- * Note: A cable soft reset shouldn't be necessary as a
- * Not_Supported reply means the partner doesn't support
- * sourcing Vconn and did not communicate with the cable.
- */
- pe_set_ready_state(port);
- return;
- }
-}
-
-__maybe_unused static void pe_vcs_force_vconn_exit(int port)
-{
- pd_timer_disable(port, PE_TIMER_TIMEOUT);
-}
-
-/*
- * PE_VCS_CBL_SEND_SOFT_RESET
- * Note - Entry is only when directed by the DPM. Protocol errors are handled
- * by the PE_SEND_SOFT_RESET state.
- */
-static void pe_vcs_cbl_send_soft_reset_entry(int port)
-{
- print_current_state(port);
-
- if (!pe_can_send_sop_prime(port)) {
- /*
- * If we're not VCONN source, return the appropriate state.
- * A VCONN swap re-triggers sending SOP' soft reset
- */
- if (pe_is_explicit_contract(port)) {
- /* Return to PE_{SRC,SNK}_Ready state */
- pe_set_ready_state(port);
- } else {
- /*
- * Not in Explicit Contract, so we must be a SRC,
- * return to PE_Src_Send_Capabilities.
- */
- set_state_pe(port, PE_SRC_SEND_CAPABILITIES);
- }
- return;
- }
-
- send_ctrl_msg(port, TCPCI_MSG_SOP_PRIME, PD_CTRL_SOFT_RESET);
- pe_sender_response_msg_entry(port);
-}
-
-static void pe_vcs_cbl_send_soft_reset_run(int port)
-{
- bool cable_soft_reset_complete = false;
- enum pe_msg_check msg_check;
-
- msg_check = pe_sender_response_msg_run(port);
-
- /* Got ACCEPT or REJECT from Cable Plug */
- if ((msg_check & PE_MSG_SENT) &&
- PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
- cable_soft_reset_complete = true;
-
- /*
- * Note: If port partner runs PD 2.0, we must use PD 2.0 to
- * communicate with the cable plug when in an explicit contract.
- *
- * PD Spec Table 6-2: Revision Interoperability during an
- * Explicit Contract
- */
- if (prl_get_rev(port, TCPCI_MSG_SOP) != PD_REV20)
- prl_set_rev(port, TCPCI_MSG_SOP_PRIME,
- PD_HEADER_REV(rx_emsg[port].header));
- }
-
- /* No GoodCRC received, cable is not present */
- if (PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
- PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
- /*
- * TODO(b/171823328): TCPMv2: Implement cable reset
- * Cable reset will only be done here if we know for certain
- * a cable is present (we've received the SOP' DiscId response).
- */
- cable_soft_reset_complete = true;
- }
-
- if (cable_soft_reset_complete ||
- pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE) ||
- (msg_check & PE_MSG_DISCARDED)) {
- if (pe_is_explicit_contract(port)) {
- /* Return to PE_{SRC,SNK}_Ready state */
- pe_set_ready_state(port);
- } else {
- /*
- * Not in Explicit Contract, so we must be a SRC,
- * return to PE_Src_Send_Capabilities.
- */
- set_state_pe(port, PE_SRC_SEND_CAPABILITIES);
- }
- }
-}
-
-static void pe_vcs_cbl_send_soft_reset_exit(int port)
-{
- pe_sender_response_msg_exit(port);
-}
-
-#endif /* CONFIG_USBC_VCONN */
-
-/*
- * PE_DR_SNK_Get_Sink_Cap and PE_SRC_Get_Sink_Cap State (shared)
- */
-static void pe_dr_get_sink_cap_entry(int port)
-{
- print_current_state(port);
-
- /* Send a Get Sink Cap Message */
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_GET_SINK_CAP);
- pe_sender_response_msg_entry(port);
-}
-
-static void pe_dr_get_sink_cap_run(int port)
-{
- int type;
- int cnt;
- int ext;
- enum pe_msg_check msg_check;
- enum tcpci_msg_type sop;
-
- /*
- * Check the state of the message sent
- */
- msg_check = pe_sender_response_msg_run(port);
-
- /*
- * Transition to PE_[SRC,SNK]_Ready when:
- * 1) A Sink_Capabilities Message is received
- * 2) Or SenderResponseTimer times out
- * 3) Or a Reject Message is received.
- *
- * Transition to PE_SEND_SOFT_RESET state when:
- * 1) An unexpected message is received
- */
- if ((msg_check & PE_MSG_SENT) &&
- PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(rx_emsg[port].header);
- cnt = PD_HEADER_CNT(rx_emsg[port].header);
- ext = PD_HEADER_EXT(rx_emsg[port].header);
- sop = PD_HEADER_GET_SOP(rx_emsg[port].header);
-
- if (ext == 0 && sop == TCPCI_MSG_SOP) {
- if ((cnt > 0) && (type == PD_DATA_SINK_CAP)) {
- uint32_t *payload =
- (uint32_t *)rx_emsg[port].buf;
- uint8_t cap_cnt = rx_emsg[port].len /
- sizeof(uint32_t);
-
- pe_set_snk_caps(port, cap_cnt, payload);
-
- dpm_evaluate_sink_fixed_pdo(port, payload[0]);
- pe_set_ready_state(port);
- return;
- } else if (cnt == 0 && (type == PD_CTRL_REJECT ||
- type == PD_CTRL_NOT_SUPPORTED)) {
- pe_set_ready_state(port);
- return;
- }
- /* Unexpected messages fall through to soft reset */
- }
-
- pe_send_soft_reset(port, sop);
- return;
- }
-
- /*
- * Transition to PE_[SRC,SNK]_Ready state when:
- * 1) SenderResponseTimer times out.
- * 2) Message was discarded.
- */
- if ((msg_check & PE_MSG_DISCARDED) ||
- pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE))
- pe_set_ready_state(port);
-}
-
-static void pe_dr_get_sink_cap_exit(int port)
-{
- pe_sender_response_msg_exit(port);
-}
-
-/*
- * PE_DR_SNK_Give_Source_Cap
- */
-static void pe_dr_snk_give_source_cap_entry(int port)
-{
- print_current_state(port);
-
- /* Send source capabilities. */
- send_source_cap(port);
-}
-
-static void pe_dr_snk_give_source_cap_run(int port)
-{
- /*
- * Transition back to PE_SNK_Ready when the Source_Capabilities message
- * has been successfully sent.
- *
- * Get Source Capabilities AMS is uninterruptible, but in case the
- * partner violates the spec then send a soft reset rather than get
- * stuck here.
- */
- if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) {
- PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE);
- set_state_pe(port, PE_SNK_READY);
- } else if (PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED)) {
- pe_send_soft_reset(port, TCPCI_MSG_SOP);
- }
-}
-
-/*
- * PE_DR_SRC_Get_Source_Cap
- */
-static void pe_dr_src_get_source_cap_entry(int port)
-{
- print_current_state(port);
-
- /* Send a Get_Source_Cap Message */
- tx_emsg[port].len = 0;
- send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_GET_SOURCE_CAP);
- pe_sender_response_msg_entry(port);
-}
-
-static void pe_dr_src_get_source_cap_run(int port)
-{
- int type;
- int cnt;
- int ext;
- enum pe_msg_check msg_check;
-
- /*
- * Check the state of the message sent
- */
- msg_check = pe_sender_response_msg_run(port);
-
- /*
- * Transition to PE_SRC_Ready when:
- * 1) A Source Capabilities Message is received.
- * 2) A Reject Message is received.
- */
- if ((msg_check & PE_MSG_SENT) &&
- PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
- PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
-
- type = PD_HEADER_TYPE(rx_emsg[port].header);
- cnt = PD_HEADER_CNT(rx_emsg[port].header);
- ext = PD_HEADER_EXT(rx_emsg[port].header);
-
- if (ext == 0) {
- if ((cnt > 0) && (type == PD_DATA_SOURCE_CAP)) {
- uint32_t *payload =
- (uint32_t *)rx_emsg[port].buf;
-
- pd_set_src_caps(port, cnt, payload);
-
- /*
- * If we'd prefer to charge from this partner,
- * then propose a PR swap.
- */
- if (pd_can_charge_from_device(port, cnt,
- payload))
- pd_request_power_swap(port);
-
- /*
- * Report dual role power capability to the
- * charge manager if present
- */
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER) &&
- pd_get_partner_dual_role_power(port))
- charge_manager_update_dualrole(port,
- CAP_DUALROLE);
-
- set_state_pe(port, PE_SRC_READY);
- } else if ((cnt == 0) && (type == PD_CTRL_REJECT ||
- type == PD_CTRL_NOT_SUPPORTED)) {
- pd_set_src_caps(port, -1, NULL);
- set_state_pe(port, PE_SRC_READY);
- } else {
- /*
- * On protocol error, consider source cap
- * retrieval a failure
- */
- pd_set_src_caps(port, -1, NULL);
- set_state_pe(port, PE_SEND_SOFT_RESET);
- }
- return;
- } else {
- pd_set_src_caps(port, -1, NULL);
- set_state_pe(port, PE_SEND_SOFT_RESET);
- return;
- }
- }
-
- /*
- * Transition to PE_SRC_Ready state when:
- * 1) the SenderResponseTimer times out.
- * 2) Message was discarded.
- */
- if ((msg_check & PE_MSG_DISCARDED) ||
- pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE))
- set_state_pe(port, PE_SRC_READY);
-}
-
-static void pe_dr_src_get_source_cap_exit(int port)
-{
- pe_sender_response_msg_exit(port);
-}
-
-const uint32_t * const pd_get_src_caps(int port)
-{
- return pe[port].src_caps;
-}
-
-void pd_set_src_caps(int port, int cnt, uint32_t *src_caps)
-{
- int i;
-
- pe[port].src_cap_cnt = cnt;
-
- for (i = 0; i < cnt; i++)
- pe[port].src_caps[i] = *src_caps++;
-}
-
-uint8_t pd_get_src_cap_cnt(int port)
-{
- if (pe[port].src_cap_cnt > 0)
- return pe[port].src_cap_cnt;
-
- return 0;
-}
-
-/* Track access to the PD discovery structures during HC execution */
-uint32_t task_access[CONFIG_USB_PD_PORT_MAX_COUNT][DISCOVERY_TYPE_COUNT];
-
-void pd_dfp_discovery_init(int port)
-{
- atomic_or(&task_access[port][TCPCI_MSG_SOP], BIT(task_get_current()));
- atomic_or(&task_access[port][TCPCI_MSG_SOP_PRIME],
- BIT(task_get_current()));
-
- memset(pe[port].discovery, 0, sizeof(pe[port].discovery));
-
-}
-
-void pd_dfp_mode_init(int port)
-{
- /*
- * Clear the VDM Setup Done and Modal Operation flags so we will
- * have a fresh discovery
- */
- PE_CLR_FLAG(port, PE_FLAGS_VDM_SETUP_DONE |
- PE_FLAGS_MODAL_OPERATION);
-
- 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);
- dp_init(port);
-
- if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE))
- tbt_init(port);
-
- if (IS_ENABLED(CONFIG_USB_PD_USB4))
- enter_usb_init(port);
-
- if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_UFP_DP))
- pd_ufp_set_dp_opos(port, 0);
-}
-
-__maybe_unused void pd_discovery_access_clear(int port,
- enum tcpci_msg_type type)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- assert(0);
-
- atomic_clear_bits(&task_access[port][type], 0xFFFFFFFF);
-}
-
-__maybe_unused bool pd_discovery_access_validate(int port,
- enum tcpci_msg_type type)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- assert(0);
-
- return !(task_access[port][type] & ~BIT(task_get_current()));
-}
-
-__maybe_unused struct pd_discovery *pd_get_am_discovery_and_notify_access(
- int port, enum tcpci_msg_type type)
-{
- atomic_or(&task_access[port][type], BIT(task_get_current()));
- return (struct pd_discovery *)pd_get_am_discovery(port, type);
-}
-
-__maybe_unused const struct pd_discovery *pd_get_am_discovery(int port,
- enum tcpci_msg_type type)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- assert(0);
- ASSERT(type < DISCOVERY_TYPE_COUNT);
-
- return &pe[port].discovery[type];
-}
-
-__maybe_unused struct partner_active_modes *pd_get_partner_active_modes(
- int port, enum tcpci_msg_type type)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- assert(0);
- ASSERT(type < AMODE_TYPE_COUNT);
- return &pe[port].partner_amodes[type];
-}
-
-__maybe_unused void pd_set_dfp_enter_mode_flag(int port, bool set)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- assert(0);
-
- if (set)
- PE_SET_FLAG(port, PE_FLAGS_MODAL_OPERATION);
- else
- PE_CLR_FLAG(port, PE_FLAGS_MODAL_OPERATION);
-}
-
-const char *pe_get_current_state(int port)
-{
- if (pe_is_running(port) && IS_ENABLED(USB_PD_DEBUG_LABELS))
- return pe_state_names[get_state_pe(port)];
- else
- return "";
-}
-
-uint32_t pe_get_flags(int port)
-{
- return pe[port].flags;
-}
-
-static __const_data const struct usb_state pe_states[] = {
- /* Super States */
-#ifdef CONFIG_USB_PD_REV30
- [PE_PRS_FRS_SHARED] = {
- .entry = pe_prs_frs_shared_entry,
- .exit = pe_prs_frs_shared_exit,
- },
-#endif
- [PE_VDM_SEND_REQUEST] = {
- .entry = pe_vdm_send_request_entry,
- .run = pe_vdm_send_request_run,
- .exit = pe_vdm_send_request_exit,
- },
-
- /* Normal States */
- [PE_SRC_STARTUP] = {
- .entry = pe_src_startup_entry,
- .run = pe_src_startup_run,
- .exit = pe_src_startup_exit,
- },
- [PE_SRC_DISCOVERY] = {
- .entry = pe_src_discovery_entry,
- .run = pe_src_discovery_run,
- },
- [PE_SRC_SEND_CAPABILITIES] = {
- .entry = pe_src_send_capabilities_entry,
- .run = pe_src_send_capabilities_run,
- .exit = pe_src_send_capabilities_exit,
- },
- [PE_SRC_NEGOTIATE_CAPABILITY] = {
- .entry = pe_src_negotiate_capability_entry,
- },
- [PE_SRC_TRANSITION_SUPPLY] = {
- .entry = pe_src_transition_supply_entry,
- .run = pe_src_transition_supply_run,
- .exit = pe_src_transition_supply_exit,
- },
- [PE_SRC_READY] = {
- .entry = pe_src_ready_entry,
- .run = pe_src_ready_run,
- },
- [PE_SRC_DISABLED] = {
- .entry = pe_src_disabled_entry,
- },
- [PE_SRC_CAPABILITY_RESPONSE] = {
- .entry = pe_src_capability_response_entry,
- .run = pe_src_capability_response_run,
- },
- [PE_SRC_HARD_RESET] = {
- .entry = pe_src_hard_reset_entry,
- .run = pe_src_hard_reset_run,
- .exit = pe_src_hard_reset_exit,
- },
- [PE_SRC_HARD_RESET_RECEIVED] = {
- .entry = pe_src_hard_reset_received_entry,
- .run = pe_src_hard_reset_received_run,
- .exit = pe_src_hard_reset_received_exit,
- },
- [PE_SRC_TRANSITION_TO_DEFAULT] = {
- .entry = pe_src_transition_to_default_entry,
- .run = pe_src_transition_to_default_run,
- },
- [PE_SNK_STARTUP] = {
- .entry = pe_snk_startup_entry,
- .run = pe_snk_startup_run,
- },
- [PE_SNK_DISCOVERY] = {
- .entry = pe_snk_discovery_entry,
- .run = pe_snk_discovery_run,
- },
- [PE_SNK_WAIT_FOR_CAPABILITIES] = {
- .entry = pe_snk_wait_for_capabilities_entry,
- .run = pe_snk_wait_for_capabilities_run,
- .exit = pe_snk_wait_for_capabilities_exit,
- },
- [PE_SNK_EVALUATE_CAPABILITY] = {
- .entry = pe_snk_evaluate_capability_entry,
- },
- [PE_SNK_SELECT_CAPABILITY] = {
- .entry = pe_snk_select_capability_entry,
- .run = pe_snk_select_capability_run,
- .exit = pe_snk_select_capability_exit,
- },
- [PE_SNK_READY] = {
- .entry = pe_snk_ready_entry,
- .run = pe_snk_ready_run,
- },
- [PE_SNK_HARD_RESET] = {
- .entry = pe_snk_hard_reset_entry,
- .run = pe_snk_hard_reset_run,
- },
- [PE_SNK_TRANSITION_TO_DEFAULT] = {
- .entry = pe_snk_transition_to_default_entry,
- .run = pe_snk_transition_to_default_run,
- },
- [PE_SNK_GIVE_SINK_CAP] = {
- .entry = pe_snk_give_sink_cap_entry,
- .run = pe_snk_give_sink_cap_run,
- },
- [PE_SNK_GET_SOURCE_CAP] = {
- .entry = pe_snk_get_source_cap_entry,
- .run = pe_snk_get_source_cap_run,
- },
- [PE_SNK_TRANSITION_SINK] = {
- .entry = pe_snk_transition_sink_entry,
- .run = pe_snk_transition_sink_run,
- .exit = pe_snk_transition_sink_exit,
- },
- [PE_SEND_SOFT_RESET] = {
- .entry = pe_send_soft_reset_entry,
- .run = pe_send_soft_reset_run,
- .exit = pe_send_soft_reset_exit,
- },
- [PE_SOFT_RESET] = {
- .entry = pe_soft_reset_entry,
- .run = pe_soft_reset_run,
- },
- [PE_SEND_NOT_SUPPORTED] = {
- .entry = pe_send_not_supported_entry,
- .run = pe_send_not_supported_run,
- },
- [PE_SRC_PING] = {
- .entry = pe_src_ping_entry,
- .run = pe_src_ping_run,
- },
- [PE_DRS_EVALUATE_SWAP] = {
- .entry = pe_drs_evaluate_swap_entry,
- .run = pe_drs_evaluate_swap_run,
- },
- [PE_DRS_CHANGE] = {
- .entry = pe_drs_change_entry,
- .run = pe_drs_change_run,
- },
- [PE_DRS_SEND_SWAP] = {
- .entry = pe_drs_send_swap_entry,
- .run = pe_drs_send_swap_run,
- .exit = pe_drs_send_swap_exit,
- },
- [PE_PRS_SRC_SNK_EVALUATE_SWAP] = {
- .entry = pe_prs_src_snk_evaluate_swap_entry,
- .run = pe_prs_src_snk_evaluate_swap_run,
- },
- [PE_PRS_SRC_SNK_TRANSITION_TO_OFF] = {
- .entry = pe_prs_src_snk_transition_to_off_entry,
- .run = pe_prs_src_snk_transition_to_off_run,
- .exit = pe_prs_src_snk_transition_to_off_exit,
- },
- [PE_PRS_SRC_SNK_ASSERT_RD] = {
- .entry = pe_prs_src_snk_assert_rd_entry,
- .run = pe_prs_src_snk_assert_rd_run,
- },
- [PE_PRS_SRC_SNK_WAIT_SOURCE_ON] = {
- .entry = pe_prs_src_snk_wait_source_on_entry,
- .run = pe_prs_src_snk_wait_source_on_run,
- .exit = pe_prs_src_snk_wait_source_on_exit,
- },
- [PE_PRS_SRC_SNK_SEND_SWAP] = {
- .entry = pe_prs_src_snk_send_swap_entry,
- .run = pe_prs_src_snk_send_swap_run,
- .exit = pe_prs_src_snk_send_swap_exit,
- },
- [PE_PRS_SNK_SRC_EVALUATE_SWAP] = {
- .entry = pe_prs_snk_src_evaluate_swap_entry,
- .run = pe_prs_snk_src_evaluate_swap_run,
- },
- /*
- * Some of the Power Role Swap actions are shared with the very
- * similar actions of Fast Role Swap.
- */
- /* State actions are shared with PE_FRS_SNK_SRC_TRANSITION_TO_OFF */
- [PE_PRS_SNK_SRC_TRANSITION_TO_OFF] = {
- .entry = pe_prs_snk_src_transition_to_off_entry,
- .run = pe_prs_snk_src_transition_to_off_run,
- .exit = pe_prs_snk_src_transition_to_off_exit,
-#ifdef CONFIG_USB_PD_REV30
- .parent = &pe_states[PE_PRS_FRS_SHARED],
-#endif /* CONFIG_USB_PD_REV30 */
- },
- /* State actions are shared with PE_FRS_SNK_SRC_ASSERT_RP */
- [PE_PRS_SNK_SRC_ASSERT_RP] = {
- .entry = pe_prs_snk_src_assert_rp_entry,
- .run = pe_prs_snk_src_assert_rp_run,
-#ifdef CONFIG_USB_PD_REV30
- .parent = &pe_states[PE_PRS_FRS_SHARED],
-#endif /* CONFIG_USB_PD_REV30 */
- },
- /* State actions are shared with PE_FRS_SNK_SRC_SOURCE_ON */
- [PE_PRS_SNK_SRC_SOURCE_ON] = {
- .entry = pe_prs_snk_src_source_on_entry,
- .run = pe_prs_snk_src_source_on_run,
- .exit = pe_prs_snk_src_source_on_exit,
-#ifdef CONFIG_USB_PD_REV30
- .parent = &pe_states[PE_PRS_FRS_SHARED],
-#endif /* CONFIG_USB_PD_REV30 */
- },
- /* State actions are shared with PE_FRS_SNK_SRC_SEND_SWAP */
- [PE_PRS_SNK_SRC_SEND_SWAP] = {
- .entry = pe_prs_snk_src_send_swap_entry,
- .run = pe_prs_snk_src_send_swap_run,
- .exit = pe_prs_snk_src_send_swap_exit,
-#ifdef CONFIG_USB_PD_REV30
- .parent = &pe_states[PE_PRS_FRS_SHARED],
-#endif /* CONFIG_USB_PD_REV30 */
- },
-#ifdef CONFIG_USBC_VCONN
- [PE_VCS_EVALUATE_SWAP] = {
- .entry = pe_vcs_evaluate_swap_entry,
- .run = pe_vcs_evaluate_swap_run,
- },
- [PE_VCS_SEND_SWAP] = {
- .entry = pe_vcs_send_swap_entry,
- .run = pe_vcs_send_swap_run,
- .exit = pe_vcs_send_swap_exit,
- },
- [PE_VCS_WAIT_FOR_VCONN_SWAP] = {
- .entry = pe_vcs_wait_for_vconn_swap_entry,
- .run = pe_vcs_wait_for_vconn_swap_run,
- .exit = pe_vcs_wait_for_vconn_swap_exit,
- },
- [PE_VCS_TURN_ON_VCONN_SWAP] = {
- .entry = pe_vcs_turn_on_vconn_swap_entry,
- .run = pe_vcs_turn_on_vconn_swap_run,
- .exit = pe_vcs_turn_on_vconn_swap_exit,
- },
- [PE_VCS_TURN_OFF_VCONN_SWAP] = {
- .entry = pe_vcs_turn_off_vconn_swap_entry,
- .run = pe_vcs_turn_off_vconn_swap_run,
- },
- [PE_VCS_SEND_PS_RDY_SWAP] = {
- .entry = pe_vcs_send_ps_rdy_swap_entry,
- .run = pe_vcs_send_ps_rdy_swap_run,
- },
- [PE_VCS_CBL_SEND_SOFT_RESET] = {
- .entry = pe_vcs_cbl_send_soft_reset_entry,
- .run = pe_vcs_cbl_send_soft_reset_run,
- .exit = pe_vcs_cbl_send_soft_reset_exit,
- },
-#endif /* CONFIG_USBC_VCONN */
- [PE_VDM_IDENTITY_REQUEST_CBL] = {
- .entry = pe_vdm_identity_request_cbl_entry,
- .run = pe_vdm_identity_request_cbl_run,
- .exit = pe_vdm_identity_request_cbl_exit,
- .parent = &pe_states[PE_VDM_SEND_REQUEST],
- },
- [PE_INIT_PORT_VDM_IDENTITY_REQUEST] = {
- .entry = pe_init_port_vdm_identity_request_entry,
- .run = pe_init_port_vdm_identity_request_run,
- .exit = pe_init_port_vdm_identity_request_exit,
- .parent = &pe_states[PE_VDM_SEND_REQUEST],
- },
- [PE_INIT_VDM_SVIDS_REQUEST] = {
- .entry = pe_init_vdm_svids_request_entry,
- .run = pe_init_vdm_svids_request_run,
- .exit = pe_init_vdm_svids_request_exit,
- .parent = &pe_states[PE_VDM_SEND_REQUEST],
- },
- [PE_INIT_VDM_MODES_REQUEST] = {
- .entry = pe_init_vdm_modes_request_entry,
- .run = pe_init_vdm_modes_request_run,
- .exit = pe_init_vdm_modes_request_exit,
- .parent = &pe_states[PE_VDM_SEND_REQUEST],
- },
- [PE_VDM_REQUEST_DPM] = {
- .entry = pe_vdm_request_dpm_entry,
- .run = pe_vdm_request_dpm_run,
- .exit = pe_vdm_request_dpm_exit,
- .parent = &pe_states[PE_VDM_SEND_REQUEST],
- },
- [PE_VDM_RESPONSE] = {
- .entry = pe_vdm_response_entry,
- .run = pe_vdm_response_run,
- .exit = pe_vdm_response_exit,
- },
- [PE_HANDLE_CUSTOM_VDM_REQUEST] = {
- .entry = pe_handle_custom_vdm_request_entry,
- .run = pe_handle_custom_vdm_request_run,
- .exit = pe_handle_custom_vdm_request_exit,
- },
- [PE_DEU_SEND_ENTER_USB] = {
- .entry = pe_enter_usb_entry,
- .run = pe_enter_usb_run,
- .exit = pe_enter_usb_exit,
- },
- [PE_WAIT_FOR_ERROR_RECOVERY] = {
- .entry = pe_wait_for_error_recovery_entry,
- .run = pe_wait_for_error_recovery_run,
- },
- [PE_BIST_TX] = {
- .entry = pe_bist_tx_entry,
- .run = pe_bist_tx_run,
- .exit = pe_bist_tx_exit,
- },
- [PE_DR_GET_SINK_CAP] = {
- .entry = pe_dr_get_sink_cap_entry,
- .run = pe_dr_get_sink_cap_run,
- .exit = pe_dr_get_sink_cap_exit,
- },
- [PE_DR_SNK_GIVE_SOURCE_CAP] = {
- .entry = pe_dr_snk_give_source_cap_entry,
- .run = pe_dr_snk_give_source_cap_run,
- },
- [PE_DR_SRC_GET_SOURCE_CAP] = {
- .entry = pe_dr_src_get_source_cap_entry,
- .run = pe_dr_src_get_source_cap_run,
- .exit = pe_dr_src_get_source_cap_exit,
- },
-#ifdef CONFIG_USB_PD_REV30
- [PE_FRS_SNK_SRC_START_AMS] = {
- .entry = pe_frs_snk_src_start_ams_entry,
- .parent = &pe_states[PE_PRS_FRS_SHARED],
- },
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- [PE_GIVE_BATTERY_CAP] = {
- .entry = pe_give_battery_cap_entry,
- .run = pe_give_battery_cap_run,
- },
- [PE_GIVE_BATTERY_STATUS] = {
- .entry = pe_give_battery_status_entry,
- .run = pe_give_battery_status_run,
- },
- [PE_SEND_ALERT] = {
- .entry = pe_send_alert_entry,
- .run = pe_send_alert_run,
- },
-#else
- [PE_SRC_CHUNK_RECEIVED] = {
- .entry = pe_chunk_received_entry,
- .run = pe_chunk_received_run,
- .exit = pe_chunk_received_exit,
- },
- [PE_SNK_CHUNK_RECEIVED] = {
- .entry = pe_chunk_received_entry,
- .run = pe_chunk_received_run,
- .exit = pe_chunk_received_exit,
- },
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-#ifdef CONFIG_USBC_VCONN
- [PE_VCS_FORCE_VCONN] = {
- .entry = pe_vcs_force_vconn_entry,
- .run = pe_vcs_force_vconn_run,
- .exit = pe_vcs_force_vconn_exit,
- },
-#endif /* CONFIG_USBC_VCONN */
-#endif /* CONFIG_USB_PD_REV30 */
-};
-
-#ifdef TEST_BUILD
-/* TODO(b/173791979): Unit tests shouldn't need to access internal states */
-const struct test_sm_data test_pe_sm_data[] = {
- {
- .base = pe_states,
- .size = ARRAY_SIZE(pe_states),
- .names = pe_state_names,
- .names_size = ARRAY_SIZE(pe_state_names),
- },
-};
-BUILD_ASSERT(ARRAY_SIZE(pe_states) == ARRAY_SIZE(pe_state_names));
-const int test_pe_sm_data_size = ARRAY_SIZE(test_pe_sm_data);
-
-void pe_set_flag(int port, int flag)
-{
- PE_SET_FLAG(port, flag);
-}
-void pe_clr_flag(int port, int flag)
-{
- PE_CLR_FLAG(port, flag);
-}
-int pe_chk_flag(int port, int flag)
-{
- return PE_CHK_FLAG(port, flag);
-}
-int pe_get_all_flags(int port)
-{
- return pe[port].flags;
-}
-void pe_set_all_flags(int port, int flags)
-{
- pe[port].flags = flags;
-}
-void pe_clr_dpm_requests(int port)
-{
- pe[port].dpm_request = 0;
-}
-#endif
diff --git a/common/usbc/usb_prl_sm.c b/common/usbc/usb_prl_sm.c
deleted file mode 100644
index a58a579775..0000000000
--- a/common/usbc/usb_prl_sm.c
+++ /dev/null
@@ -1,2471 +0,0 @@
-/* Copyright 2019 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.
- */
-
-#include "battery.h"
-#include "battery_smart.h"
-#include "board.h"
-#include "charge_manager.h"
-#include "charge_state.h"
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "cros_version.h"
-#include "ec_commands.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "registers.h"
-#include "system.h"
-#include "task.h"
-#include "tcpm/tcpm.h"
-#include "util.h"
-#include "usb_charge.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "usb_pd_timer.h"
-#include "usb_pe_sm.h"
-#include "usb_prl_sm.h"
-#include "usb_tc_sm.h"
-#include "usb_emsg.h"
-#include "usb_sm.h"
-#include "vpd_api.h"
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#else
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif
-
-/*
- * Define DEBUG_PRINT_FLAG_NAMES to print flag names when set and cleared.
- */
-#undef DEBUG_PRINT_FLAG_NAMES
-
-#ifdef DEBUG_PRINT_FLAG_NAMES
-__maybe_unused static void print_flag(const char *group,
- int set_or_clear,
- int flag);
-#define SET_FLAG(group, flags, flag) \
- do { \
- print_flag(group, 1, flag); \
- atomic_or(flags, (flag)); \
- } while (0)
-#define CLR_FLAG(group, flags, flag) \
- do { \
- int before = *flags; \
- atomic_clear_bits(flags, (flag)); \
- if (*flags != before) \
- print_flag(group, 0, flag); \
- } while (0)
-#else
-#define SET_FLAG(group, flags, flag) atomic_or(flags, (flag))
-#define CLR_FLAG(group, flags, flag) atomic_clear_bits(flags, (flag))
-#endif
-
-
-#define RCH_SET_FLAG(port, flag) SET_FLAG("RCH", &rch[port].flags, (flag))
-#define RCH_CLR_FLAG(port, flag) CLR_FLAG("RCH", &rch[port].flags, (flag))
-#define RCH_CHK_FLAG(port, flag) (rch[port].flags & (flag))
-
-#define TCH_SET_FLAG(port, flag) SET_FLAG("TCH", &tch[port].flags, (flag))
-#define TCH_CLR_FLAG(port, flag) CLR_FLAG("TCH", &tch[port].flags, (flag))
-#define TCH_CHK_FLAG(port, flag) (tch[port].flags & (flag))
-
-#define PRL_TX_SET_FLAG(port, flag) \
- SET_FLAG("PRL_TX", &prl_tx[port].flags, (flag))
-#define PRL_TX_CLR_FLAG(port, flag) \
- CLR_FLAG("PRL_TX", &prl_tx[port].flags, (flag))
-#define PRL_TX_CHK_FLAG(port, flag) (prl_tx[port].flags & (flag))
-
-#define PRL_HR_SET_FLAG(port, flag) \
- SET_FLAG("PRL_HR", &prl_hr[port].flags, (flag))
-#define PRL_HR_CLR_FLAG(port, flag) \
- CLR_FLAG("PRL_HR", &prl_hr[port].flags, (flag))
-#define PRL_HR_CHK_FLAG(port, flag) (prl_hr[port].flags & (flag))
-
-#define PDMSG_SET_FLAG(port, flag) SET_FLAG("PDMSG", &pdmsg[port].flags, (flag))
-#define PDMSG_CLR_FLAG(port, flag) CLR_FLAG("PDMSG", &pdmsg[port].flags, (flag))
-#define PDMSG_CHK_FLAG(port, flag) (pdmsg[port].flags & (flag))
-
-/* Protocol Layer Flags */
-/*
- * NOTE:
- * These flags are used in multiple state machines and could have
- * different meanings in each state machine.
- */
-/* Flag to note message transmission completed */
-#define PRL_FLAGS_TX_COMPLETE BIT(0)
-/* Flag to note that PRL requested to set SINK_NG CC state */
-#define PRL_FLAGS_SINK_NG BIT(1)
-/* Flag to note PRL waited for SINK_OK CC state before transmitting */
-#define PRL_FLAGS_WAIT_SINK_OK BIT(2)
-/* Flag to note transmission error occurred */
-#define PRL_FLAGS_TX_ERROR BIT(3)
-/* Flag to note PE triggered a hard reset */
-#define PRL_FLAGS_PE_HARD_RESET BIT(4)
-/* Flag to note hard reset has completed */
-#define PRL_FLAGS_HARD_RESET_COMPLETE BIT(5)
-/* Flag to note port partner sent a hard reset */
-#define PRL_FLAGS_PORT_PARTNER_HARD_RESET BIT(6)
-/*
- * Flag to note a message transmission has been requested. It is only cleared
- * when we send the message to the TCPC layer.
- */
-#define PRL_FLAGS_MSG_XMIT BIT(7)
-/* Flag to note a message was received */
-#define PRL_FLAGS_MSG_RECEIVED BIT(8)
-/* Flag to note aborting current TX message, not currently set */
-#define PRL_FLAGS_ABORT BIT(9)
-/* Flag to note current TX message uses chunking */
-#define PRL_FLAGS_CHUNKING BIT(10)
-
-struct bit_name {
- int value;
- const char *name;
-};
-
-static __const_data struct bit_name flag_bit_names[] = {
- { PRL_FLAGS_TX_COMPLETE, "PRL_FLAGS_TX_COMPLETE" },
- { PRL_FLAGS_SINK_NG, "PRL_FLAGS_SINK_NG" },
- { PRL_FLAGS_WAIT_SINK_OK, "PRL_FLAGS_WAIT_SINK_OK" },
- { PRL_FLAGS_TX_ERROR, "PRL_FLAGS_TX_ERROR" },
- { PRL_FLAGS_PE_HARD_RESET, "PRL_FLAGS_PE_HARD_RESET" },
- { PRL_FLAGS_HARD_RESET_COMPLETE, "PRL_FLAGS_HARD_RESET_COMPLETE" },
- { PRL_FLAGS_PORT_PARTNER_HARD_RESET,
- "PRL_FLAGS_PORT_PARTNER_HARD_RESET" },
- { PRL_FLAGS_MSG_XMIT, "PRL_FLAGS_MSG_XMIT" },
- { PRL_FLAGS_MSG_RECEIVED, "PRL_FLAGS_MSG_RECEIVED" },
- { PRL_FLAGS_ABORT, "PRL_FLAGS_ABORT" },
- { PRL_FLAGS_CHUNKING, "PRL_FLAGS_CHUNKING" },
-};
-
-__maybe_unused static void print_bits(const char *group,
- const char *desc,
- int value,
- struct bit_name *names,
- int names_size)
-{
- int i;
-
- CPRINTF("%s %s 0x%x : ", group, desc, value);
- for (i = 0; i < names_size; i++) {
- if (value & names[i].value)
- CPRINTF("%s | ", names[i].name);
- value &= ~names[i].value;
- }
- if (value != 0)
- CPRINTF("0x%x", value);
- CPRINTF("\n");
-}
-
-__maybe_unused static void print_flag(const char *group,
- int set_or_clear,
- int flag)
-{
- print_bits(group, set_or_clear ? "Set" : "Clr", flag, flag_bit_names,
- ARRAY_SIZE(flag_bit_names));
-}
-
-/* PD counter definitions */
-#define PD_MESSAGE_ID_COUNT 7
-
-/* Size of PDMSG Chunk Buffer */
-#define CHK_BUF_SIZE 7
-#define CHK_BUF_SIZE_BYTES 28
-
-/*
- * Debug log level - higher number == more log
- * Level 0: disabled
- * Level 1: not currently used
- * Level 2: plus non-ping messages
- * Level 3: plus ping packet and PRL states
- *
- * Note that higher log level causes timing changes and thus may affect
- * performance.
- */
-#ifdef CONFIG_USB_PD_DEBUG_LEVEL
-static const enum debug_level prl_debug_level = CONFIG_USB_PD_DEBUG_LEVEL;
-#else
-static enum debug_level prl_debug_level = DEBUG_LEVEL_1;
-#endif
-
-static enum sm_local_state local_state[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Protocol Transmit States (Section 6.11.2.2) */
-enum usb_prl_tx_state {
- PRL_TX_PHY_LAYER_RESET,
- PRL_TX_WAIT_FOR_MESSAGE_REQUEST,
- PRL_TX_LAYER_RESET_FOR_TRANSMIT,
- PRL_TX_WAIT_FOR_PHY_RESPONSE,
- PRL_TX_SRC_SOURCE_TX,
- PRL_TX_SNK_START_AMS,
- PRL_TX_SRC_PENDING,
- PRL_TX_SNK_PENDING,
- PRL_TX_DISCARD_MESSAGE,
-};
-
-/* Protocol Hard Reset States (Section 6.11.2.4) */
-enum usb_prl_hr_state {
- PRL_HR_WAIT_FOR_REQUEST,
- PRL_HR_RESET_LAYER,
- PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE,
- PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE,
-};
-
-/* Chunked Rx states (Section 6.11.2.1.2) */
-enum usb_rch_state {
- RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER,
- RCH_PASS_UP_MESSAGE,
- RCH_PROCESSING_EXTENDED_MESSAGE,
- RCH_REQUESTING_CHUNK,
- RCH_WAITING_CHUNK,
- RCH_REPORT_ERROR,
-};
-
-/* Chunked Tx states (Section 6.11.2.1.3) */
-enum usb_tch_state {
- TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE,
- TCH_WAIT_FOR_TRANSMISSION_COMPLETE,
- TCH_CONSTRUCT_CHUNKED_MESSAGE,
- TCH_SENDING_CHUNKED_MESSAGE,
- TCH_WAIT_CHUNK_REQUEST,
- TCH_MESSAGE_RECEIVED,
- TCH_MESSAGE_SENT,
- TCH_REPORT_ERROR,
-};
-
-static const char * const prl_tx_state_names[] = {
- [PRL_TX_PHY_LAYER_RESET] = "PRL_TX_PHY_LAYER_RESET",
- [PRL_TX_WAIT_FOR_MESSAGE_REQUEST] = "PRL_TX_WAIT_FOR_MESSAGE_REQUEST",
- [PRL_TX_LAYER_RESET_FOR_TRANSMIT] = "PRL_TX_LAYER_RESET_FOR_TRANSMIT",
- [PRL_TX_WAIT_FOR_PHY_RESPONSE] = "PRL_TX_WAIT_FOR_PHY_RESPONSE",
- [PRL_TX_SRC_SOURCE_TX] = "PRL_TX_SRC_SOURCE_TX",
- [PRL_TX_SNK_START_AMS] = "PRL_TX_SNK_START_AMS",
- [PRL_TX_SRC_PENDING] = "PRL_TX_SRC_PENDING",
- [PRL_TX_SNK_PENDING] = "PRL_TX_SNK_PENDING",
- [PRL_TX_DISCARD_MESSAGE] = "PRL_TX_DISCARD_MESSAGE",
-};
-
-static const char * const prl_hr_state_names[] = {
- [PRL_HR_WAIT_FOR_REQUEST] = "PRL_HR_WAIT_FOR_REQUEST",
- [PRL_HR_RESET_LAYER] = "PRL_HR_RESET_LAYER",
- [PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE]
- = "PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE",
- [PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE]
- = "PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE",
-};
-
-__maybe_unused static const char * const rch_state_names[] = {
- [RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER]
- = "RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER",
- [RCH_PASS_UP_MESSAGE] = "RCH_PASS_UP_MESSAGE",
- [RCH_PROCESSING_EXTENDED_MESSAGE] = "RCH_PROCESSING_EXTENDED_MESSAGE",
- [RCH_REQUESTING_CHUNK] = "RCH_REQUESTING_CHUNK",
- [RCH_WAITING_CHUNK] = "RCH_WAITING_CHUNK",
- [RCH_REPORT_ERROR] = "RCH_REPORT_ERROR",
-};
-
-__maybe_unused static const char * const tch_state_names[] = {
- [TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE]
- = "TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE",
- [TCH_WAIT_FOR_TRANSMISSION_COMPLETE]
- = "TCH_WAIT_FOR_TRANSMISSION_COMPLETE",
- [TCH_CONSTRUCT_CHUNKED_MESSAGE] = "TCH_CONSTRUCT_CHUNKED_MESSAGE",
- [TCH_SENDING_CHUNKED_MESSAGE] = "TCH_SENDING_CHUNKED_MESSAGE",
- [TCH_WAIT_CHUNK_REQUEST] = "TCH_WAIT_CHUNK_REQUEST",
- [TCH_MESSAGE_RECEIVED] = "TCH_MESSAGE_RECEIVED",
- [TCH_MESSAGE_SENT] = "TCH_MESSAGE_SENT",
- [TCH_REPORT_ERROR] = "TCH_REPORT_ERROR",
-};
-
-/* Forward declare full list of states. Index by above enums. */
-static const struct usb_state prl_tx_states[];
-static const struct usb_state prl_hr_states[];
-
-__maybe_unused static const struct usb_state rch_states[];
-__maybe_unused static const struct usb_state tch_states[];
-
-/* Chunked Rx State Machine Object */
-static struct rx_chunked {
- /* state machine context */
- struct sm_ctx ctx;
- /* PRL_FLAGS */
- uint32_t flags;
- /* error to report when moving to rch_report_error state */
- enum pe_error error;
-} rch[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Chunked Tx State Machine Object */
-static struct tx_chunked {
- /* state machine context */
- struct sm_ctx ctx;
- /* state machine flags */
- uint32_t flags;
- /* error to report when moving to tch_report_error state */
- enum pe_error error;
-} tch[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Message Reception State Machine Object */
-static struct protocol_layer_rx {
- /* received message type */
- enum tcpci_msg_type sop;
- /* message ids for all valid port partners */
- int msg_id[NUM_SOP_STAR_TYPES];
-} prl_rx[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Message Transmission State Machine Object */
-static struct protocol_layer_tx {
- /* state machine context */
- struct sm_ctx ctx;
- /* state machine flags */
- uint32_t flags;
- /* last message type we transmitted */
- enum tcpci_msg_type last_xmit_type;
- /* message id counters for all 6 port partners */
- uint32_t msg_id_counter[NUM_SOP_STAR_TYPES];
- /* transmit status */
- int xmit_status;
-} prl_tx[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Hard Reset State Machine Object */
-static struct protocol_hard_reset {
- /* state machine context */
- struct sm_ctx ctx;
- /* state machine flags */
- uint32_t flags;
-} prl_hr[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Chunking Message Object */
-static struct pd_message {
- /* message status flags */
- uint32_t flags;
- /* SOP* */
- enum tcpci_msg_type xmit_type;
- /* type of message */
- uint8_t msg_type;
- /* PD revision */
- enum pd_rev_type rev[NUM_SOP_STAR_TYPES];
- /* Number of 32-bit objects in chk_buf */
- uint16_t data_objs;
- /* temp chunk buffer */
- uint32_t tx_chk_buf[CHK_BUF_SIZE];
- uint32_t rx_chk_buf[CHK_BUF_SIZE];
- uint32_t chunk_number_expected;
- uint32_t num_bytes_received;
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- /* extended message */
- uint8_t ext;
- uint32_t chunk_number_to_send;
- uint32_t send_offset;
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-} pdmsg[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-struct extended_msg rx_emsg[CONFIG_USB_PD_PORT_MAX_COUNT];
-struct extended_msg tx_emsg[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Common Protocol Layer Message Transmission */
-static void prl_tx_construct_message(int port);
-static void prl_rx_wait_for_phy_message(const int port, int evt);
-static void prl_copy_msg_to_buffer(int port);
-
-#ifndef CONFIG_USB_PD_REV30
-GEN_NOT_SUPPORTED(PRL_TX_SRC_SOURCE_TX);
-#define PRL_TX_SRC_SOURCE_TX PRL_TX_SRC_SOURCE_TX_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(PRL_TX_SNK_START_AMS);
-#define PRL_TX_SNK_START_AMS PRL_TX_SNK_START_AMS_NOT_SUPPORTED
-
-GEN_NOT_SUPPORTED(RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER);
-#define RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER \
- RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(RCH_PASS_UP_MESSAGE);
-#define RCH_PASS_UP_MESSAGE RCH_PASS_UP_MESSAGE_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(RCH_PROCESSING_EXTENDED_MESSAGE);
-#define RCH_PROCESSING_EXTENDED_MESSAGE \
- RCH_PROCESSING_EXTENDED_MESSAGE_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(RCH_REQUESTING_CHUNK);
-#define RCH_REQUESTING_CHUNK RCH_REQUESTING_CHUNK_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(RCH_WAITING_CHUNK);
-#define RCH_WAITING_CHUNK RCH_WAITING_CHUNK_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(RCH_REPORT_ERROR);
-#define RCH_REPORT_ERROR RCH_REPORT_ERROR_NOT_SUPPORTED
-
-GEN_NOT_SUPPORTED(TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
-#define TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE \
- TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(TCH_WAIT_FOR_TRANSMISSION_COMPLETE);
-#define TCH_WAIT_FOR_TRANSMISSION_COMPLETE \
- TCH_WAIT_FOR_TRANSMISSION_COMPLETE_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(TCH_CONSTRUCT_CHUNKED_MESSAGE);
-#define TCH_CONSTRUCT_CHUNKED_MESSAGE \
- TCH_CONSTRUCT_CHUNKED_MESSAGE_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(TCH_SENDING_CHUNKED_MESSAGE);
-#define TCH_SENDING_CHUNKED_MESSAGE TCH_SENDING_CHUNKED_MESSAGE_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(TCH_WAIT_CHUNK_REQUEST);
-#define TCH_WAIT_CHUNK_REQUEST TCH_WAIT_CHUNK_REQUEST_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(TCH_MESSAGE_RECEIVED);
-#define TCH_MESSAGE_RECEIVED TCH_MESSAGE_RECEIVED_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(TCH_MESSAGE_SENT);
-#define TCH_MESSAGE_SENT TCH_MESSAGE_SENT_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(TCH_REPORT_ERROR);
-#define TCH_REPORT_ERROR TCH_REPORT_ERROR_NOT_SUPPORTED
-#endif /* !CONFIG_USB_PD_REV30 */
-
-/* To store the time stamp when TCPC sets TX Complete Success */
-static timestamp_t tcpc_tx_success_ts[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Set the protocol transmit statemachine to a new state. */
-static void set_state_prl_tx(const int port,
- const enum usb_prl_tx_state new_state)
-{
- set_state(port, &prl_tx[port].ctx, &prl_tx_states[new_state]);
-}
-
-/* Get the protocol transmit statemachine's current state. */
-test_export_static enum usb_prl_tx_state prl_tx_get_state(const int port)
-{
- return prl_tx[port].ctx.current - &prl_tx_states[0];
-}
-
-/* Print the protocol transmit statemachine's current state. */
-static void print_current_prl_tx_state(const int port)
-{
- if (prl_debug_level >= DEBUG_LEVEL_3)
- CPRINTS("C%d: %s", port,
- prl_tx_state_names[prl_tx_get_state(port)]);
-}
-
-/* Set the hard reset statemachine to a new state. */
-static void set_state_prl_hr(const int port,
- const enum usb_prl_hr_state new_state)
-{
- set_state(port, &prl_hr[port].ctx, &prl_hr_states[new_state]);
-}
-
-/* Get the hard reset statemachine's current state. */
-enum usb_prl_hr_state prl_hr_get_state(const int port)
-{
- return prl_hr[port].ctx.current - &prl_hr_states[0];
-}
-
-/* Print the hard reset statemachine's current state. */
-static void print_current_prl_hr_state(const int port)
-{
- if (prl_debug_level >= DEBUG_LEVEL_3)
- CPRINTS("C%d: %s", port,
- prl_hr_state_names[prl_hr_get_state(port)]);
-}
-
-/* Set the chunked Rx statemachine to a new state. */
-static void set_state_rch(const int port, const enum usb_rch_state new_state)
-{
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES))
- set_state(port, &rch[port].ctx, &rch_states[new_state]);
-}
-
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
-/* Get the chunked Rx statemachine's current state. */
-test_export_static enum usb_rch_state rch_get_state(const int port)
-{
- return rch[port].ctx.current - &rch_states[0];
-}
-
-/* Print the chunked Rx statemachine's current state. */
-static void print_current_rch_state(const int port)
-{
- if (prl_debug_level >= DEBUG_LEVEL_3)
- CPRINTS("C%d: %s", port,
- rch_state_names[rch_get_state(port)]);
-}
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-
-/* Set the chunked Tx statemachine to a new state. */
-static void set_state_tch(const int port, const enum usb_tch_state new_state)
-{
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES))
- set_state(port, &tch[port].ctx, &tch_states[new_state]);
-}
-
-/* Get the chunked Tx statemachine's current state. */
-test_export_static enum usb_tch_state tch_get_state(const int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES))
- return tch[port].ctx.current - &tch_states[0];
- else
- return 0;
-}
-
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
-/* Print the chunked Tx statemachine's current state. */
-static void print_current_tch_state(const int port)
-{
- if (prl_debug_level >= DEBUG_LEVEL_3)
- CPRINTS("C%d: %s", port,
- tch_state_names[tch_get_state(port)]);
-}
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-
-
-timestamp_t prl_get_tcpc_tx_success_ts(int port)
-{
- return tcpc_tx_success_ts[port];
-}
-
-/* Sets the time stamp when TCPC reports TX success. */
-static void set_tcpc_tx_success_ts(int port)
-{
- tcpc_tx_success_ts[port] = get_time();
-}
-
-void pd_transmit_complete(int port, int status)
-{
- if (status == TCPC_TX_COMPLETE_SUCCESS)
- set_tcpc_tx_success_ts(port);
- prl_tx[port].xmit_status = status;
-}
-
-void pd_execute_hard_reset(int port)
-{
- /* Only allow async. function calls when state machine is running */
- if (!prl_is_running(port))
- return;
-
- PRL_HR_SET_FLAG(port, PRL_FLAGS_PORT_PARTNER_HARD_RESET);
- set_state_prl_hr(port, PRL_HR_RESET_LAYER);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void prl_execute_hard_reset(int port)
-{
- /* Only allow async. function calls when state machine is running */
- if (!prl_is_running(port))
- return;
-
- PRL_HR_SET_FLAG(port, PRL_FLAGS_PE_HARD_RESET);
- set_state_prl_hr(port, PRL_HR_RESET_LAYER);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-int prl_is_running(int port)
-{
- return local_state[port] == SM_RUN;
-}
-
-static void prl_init(int port)
-{
- int i;
- const struct sm_ctx cleared = {};
-
- /*
- * flags without PRL_FLAGS_SINK_NG present means we are initially
- * in SinkTxOK state
- */
- prl_tx[port].flags = 0;
- if (IS_ENABLED(CONFIG_USB_PD_REV30))
- typec_select_src_collision_rp(port, SINK_TX_OK);
- prl_tx[port].last_xmit_type = TCPCI_MSG_SOP;
- prl_tx[port].xmit_status = TCPC_TX_UNSET;
-
- if (IS_ENABLED(CONFIG_USB_PD_REV30)) {
- tch[port].flags = 0;
- rch[port].flags = 0;
- }
-
- pdmsg[port].flags = 0;
-
- prl_hr[port].flags = 0;
-
- for (i = 0; i < NUM_SOP_STAR_TYPES; i++) {
- prl_rx[port].msg_id[i] = -1;
- prl_tx[port].msg_id_counter[i] = 0;
- }
-
- pd_timer_disable_range(port, PR_TIMER_RANGE);
-
- /* Clear state machines and set initial states */
- prl_tx[port].ctx = cleared;
- set_state_prl_tx(port, PRL_TX_PHY_LAYER_RESET);
-
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) {
- rch[port].ctx = cleared;
- set_state_rch(port, RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER);
-
- tch[port].ctx = cleared;
- set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
- }
-
- prl_hr[port].ctx = cleared;
- set_state_prl_hr(port, PRL_HR_WAIT_FOR_REQUEST);
-}
-
-bool prl_is_busy(int port)
-{
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- return rch_get_state(port) !=
- RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER ||
- tch_get_state(port) !=
- TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE;
-#else
- return false;
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-}
-
-void prl_set_debug_level(enum debug_level debug_level)
-{
-#ifndef CONFIG_USB_PD_DEBUG_LEVEL
- prl_debug_level = debug_level;
-#endif
-}
-
-void prl_hard_reset_complete(int port)
-{
- PRL_HR_SET_FLAG(port, PRL_FLAGS_HARD_RESET_COMPLETE);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void prl_send_ctrl_msg(int port,
- enum tcpci_msg_type type,
- enum pd_ctrl_msg_type msg)
-{
- pdmsg[port].xmit_type = type;
- pdmsg[port].msg_type = msg;
- pdmsg[port].data_objs = 0;
- tx_emsg[port].len = 0;
-
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- pdmsg[port].ext = 0;
-
- TCH_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
-#else
- PRL_TX_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void prl_send_data_msg(int port,
- enum tcpci_msg_type type,
- enum pd_data_msg_type msg)
-{
- pdmsg[port].xmit_type = type;
- pdmsg[port].msg_type = msg;
-
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- pdmsg[port].ext = 0;
-
- TCH_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
-#else
- prl_copy_msg_to_buffer(port);
- PRL_TX_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
-void prl_send_ext_data_msg(int port,
- enum tcpci_msg_type type,
- enum pd_ext_msg_type msg)
-{
- pdmsg[port].xmit_type = type;
- pdmsg[port].msg_type = msg;
- pdmsg[port].ext = 1;
-
- TCH_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-
-void prl_set_default_pd_revision(int port)
-{
- /*
- * Initialize to highest revision supported. If the port or cable
- * partner doesn't support this revision, the Protocol Engine will
- * lower this value to the revision supported by the partner.
- */
- pdmsg[port].rev[TCPCI_MSG_SOP] = PD_REVISION;
- pdmsg[port].rev[TCPCI_MSG_SOP_PRIME] = PD_REVISION;
- pdmsg[port].rev[TCPCI_MSG_SOP_PRIME_PRIME] = PD_REVISION;
- pdmsg[port].rev[TCPCI_MSG_SOP_DEBUG_PRIME] = PD_REVISION;
- pdmsg[port].rev[TCPCI_MSG_SOP_DEBUG_PRIME_PRIME] = PD_REVISION;
-}
-
-void prl_reset_soft(int port)
-{
- /* Do not change negotiated PD Revision Specification level */
- local_state[port] = SM_INIT;
-
- /* Ensure we process the reset quickly */
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void prl_run(int port, int evt, int en)
-{
- switch (local_state[port]) {
- case SM_PAUSED:
- if (!en)
- break;
- /* fall through */
- case SM_INIT:
- prl_init(port);
- local_state[port] = SM_RUN;
- /* fall through */
- case SM_RUN:
- if (!en) {
- /* Disable RX */
- if (IS_ENABLED(CONFIG_USB_CTVPD) ||
- IS_ENABLED(CONFIG_USB_VPD))
- vpd_rx_enable(0);
- else
- tcpm_set_rx_enable(port, 0);
-
- local_state[port] = SM_PAUSED;
- break;
- }
-
- /* Run Protocol Layer Hard Reset state machine */
- run_state(port, &prl_hr[port].ctx);
-
- /*
- * If the Hard Reset state machine is active, then there is no
- * need to execute any other PRL state machines. When the hard
- * reset is complete, all PRL state machines will have been
- * reset.
- */
- if (prl_hr_get_state(port) == PRL_HR_WAIT_FOR_REQUEST) {
-
- /* Run Protocol Layer Message Reception */
- prl_rx_wait_for_phy_message(port, evt);
-
-
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) {
- /*
- * Run RX Chunked state machine after prl_rx.
- * This is what informs the PE of incoming
- * message. Its input is prl_rx
- */
- run_state(port, &rch[port].ctx);
-
- /*
- * Run TX Chunked state machine before prl_tx
- * in case we need to split an extended message
- * and prl_tx can send it for us
- */
- run_state(port, &tch[port].ctx);
- }
-
- /* Run Protocol Layer Message Tx state machine */
- run_state(port, &prl_tx[port].ctx);
-
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES))
- /*
- * Run TX Chunked state machine again after
- * prl_tx so we can handle passing TX_COMPLETE
- * (or failure) up to PE in a single iteration.
- */
- run_state(port, &tch[port].ctx);
- }
- break;
- }
-}
-
-void prl_set_rev(int port, enum tcpci_msg_type type,
- enum pd_rev_type rev)
-{
- /* We only store revisions for SOP* types. */
- ASSERT(type < NUM_SOP_STAR_TYPES);
-
- pdmsg[port].rev[type] = rev;
-}
-
-enum pd_rev_type prl_get_rev(int port, enum tcpci_msg_type type)
-{
- /* We only store revisions for SOP* types. */
- ASSERT(type < NUM_SOP_STAR_TYPES);
-
- return pdmsg[port].rev[type];
-}
-
-static void prl_copy_msg_to_buffer(int port)
-{
- /*
- * Control Messages will have a length of 0 and
- * no need to spend time with the tx_chk_buf
- * for this path
- */
- if (tx_emsg[port].len == 0) {
- pdmsg[port].data_objs = 0;
- return;
- }
-
- /*
- * Make sure the Policy Engine isn't sending
- * more than CHK_BUF_SIZE_BYTES. If so,
- * truncate len. This will surely send a
- * malformed packet resulting in the port
- * partner soft\hard resetting us.
- */
- if (tx_emsg[port].len > CHK_BUF_SIZE_BYTES)
- tx_emsg[port].len = CHK_BUF_SIZE_BYTES;
-
- /* Copy message to chunked buffer */
- memset((uint8_t *)pdmsg[port].tx_chk_buf, 0, CHK_BUF_SIZE_BYTES);
- memcpy((uint8_t *)pdmsg[port].tx_chk_buf, (uint8_t *)tx_emsg[port].buf,
- tx_emsg[port].len);
- /*
- * Pad length to 4-byte boundary and
- * convert to number of 32-bit objects.
- * Since the value is shifted right by 2,
- * no need to explicitly clear the lower
- * 2-bits.
- */
- pdmsg[port].data_objs = (tx_emsg[port].len + 3) >> 2;
-}
-
-static __maybe_unused int pdmsg_xmit_type_is_rev30(const int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_REV30))
- return ((pdmsg[port].xmit_type < NUM_SOP_STAR_TYPES)
- && (prl_get_rev(port, pdmsg[port].xmit_type) == PD_REV30));
- else
- return 0;
-}
-
-/* Returns true if the SOP port partner operates at PD rev3.0 */
-static bool is_sop_rev30(const int port)
-{
- return IS_ENABLED(CONFIG_USB_PD_REV30) &&
- prl_get_rev(port, TCPCI_MSG_SOP) == PD_REV30;
-}
-
-/* Common Protocol Layer Message Transmission */
-static void prl_tx_phy_layer_reset_entry(const int port)
-{
- print_current_prl_tx_state(port);
-
- if (IS_ENABLED(CONFIG_USB_CTVPD)
- || IS_ENABLED(CONFIG_USB_VPD)) {
- vpd_rx_enable(pd_is_connected(port));
- } else {
- /* Note: can't clear PHY messages due to TCPC architecture */
- /* Enable communications*/
- tcpm_set_rx_enable(port, pd_is_connected(port));
- }
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_MESSAGE_REQUEST);
-}
-
-static void prl_tx_wait_for_message_request_entry(const int port)
-{
- /* No phy layer response is pending */
- prl_tx[port].xmit_status = TCPC_TX_UNSET;
- print_current_prl_tx_state(port);
-}
-
-static void prl_tx_wait_for_message_request_run(const int port)
-{
- /* Clear any AMS flags and state if we are no longer in an AMS */
- if (IS_ENABLED(CONFIG_USB_PD_REV30) && !pe_in_local_ams(port)) {
- /* Note PRL_Tx_Src_Sink_Tx is embedded here. */
- if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_SINK_NG)) {
- typec_select_src_collision_rp(port, SINK_TX_OK);
- typec_update_cc(port);
- }
- PRL_TX_CLR_FLAG(port,
- PRL_FLAGS_SINK_NG | PRL_FLAGS_WAIT_SINK_OK);
- }
-
- /*
- * Check if we are starting an AMS and need to wait and/or set the CC
- * lines appropriately.
- */
- if (IS_ENABLED(CONFIG_USB_PD_REV30) && is_sop_rev30(port) &&
- pe_in_local_ams(port)) {
- if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_SINK_NG |
- PRL_FLAGS_WAIT_SINK_OK)) {
- /*
- * If we are already in an AMS then allow the
- * multi-message AMS to continue, even if we
- * swap power roles.
- *
- * Fall Through using the current AMS
- */
- } else {
- /*
- * Start of SRC AMS notification received from
- * Policy Engine
- */
- if (pd_get_power_role(port) == PD_ROLE_SOURCE) {
- PRL_TX_SET_FLAG(port, PRL_FLAGS_SINK_NG);
- set_state_prl_tx(port, PRL_TX_SRC_SOURCE_TX);
- } else {
- PRL_TX_SET_FLAG(port, PRL_FLAGS_WAIT_SINK_OK);
- set_state_prl_tx(port, PRL_TX_SNK_START_AMS);
- }
- return;
- }
- }
-
- /* Handle non Rev 3.0 or subsequent messages in AMS sequence */
- if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) {
- PRL_TX_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT);
- /*
- * Soft Reset Message Message pending
- */
- if ((pdmsg[port].msg_type == PD_CTRL_SOFT_RESET) &&
- (tx_emsg[port].len == 0)) {
- set_state_prl_tx(port, PRL_TX_LAYER_RESET_FOR_TRANSMIT);
- }
- /*
- * Message pending (except Soft Reset)
- */
- else {
- /* NOTE: PRL_TX_Construct_Message State embedded here */
- prl_tx_construct_message(port);
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_PHY_RESPONSE);
- }
-
- return;
- }
-}
-
-static void increment_msgid_counter(int port)
-{
- /* If the last message wasn't an SOP* message, no need to increment */
- if (prl_tx[port].last_xmit_type >= NUM_SOP_STAR_TYPES)
- return;
-
- prl_tx[port].msg_id_counter[prl_tx[port].last_xmit_type] =
- (prl_tx[port].msg_id_counter[prl_tx[port].last_xmit_type] + 1) &
- PD_MESSAGE_ID_COUNT;
-}
-
-/*
- * PrlTxDiscard
- */
-static void prl_tx_discard_message_entry(const int port)
-{
- print_current_prl_tx_state(port);
-
- /*
- * Discard queued message
- * Note: We differ from spec here, which allows us to not discard on
- * incoming SOP' or SOP''. However this would get the TCH out of sync.
- *
- * prl_tx will be set to this state following message reception in
- * prl_rx. So this path will be entered following each rx message. If
- * this state is entered, and there is either a message from the PE
- * pending, or if a message was passed to the phy and there is either no
- * response yet, or it was discarded in the phy layer, then a tx message
- * discard event has been detected.
- */
- if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT) ||
- prl_tx[port].xmit_status == TCPC_TX_WAIT ||
- prl_tx[port].xmit_status == TCPC_TX_COMPLETE_DISCARDED) {
- PRL_TX_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT);
- increment_msgid_counter(port);
- pe_report_discard(port);
- }
-
- set_state_prl_tx(port, PRL_TX_PHY_LAYER_RESET);
-}
-
-#ifdef CONFIG_USB_PD_REV30
-/*
- * PrlTxSrcSourceTx
- */
-static void prl_tx_src_source_tx_entry(const int port)
-{
- print_current_prl_tx_state(port);
-
- /* Set Rp = SinkTxNG */
- typec_select_src_collision_rp(port, SINK_TX_NG);
- typec_update_cc(port);
-}
-
-static void prl_tx_src_source_tx_run(const int port)
-{
- if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) {
- /*
- * Don't clear pending XMIT flag here. Wait until we send so
- * we can detect if we dropped this message or not.
- */
- set_state_prl_tx(port, PRL_TX_SRC_PENDING);
- }
-}
-
-/*
- * PrlTxSnkStartAms
- */
-static void prl_tx_snk_start_ams_entry(const int port)
-{
- print_current_prl_tx_state(port);
-}
-
-static void prl_tx_snk_start_ams_run(const int port)
-{
- if (PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) {
- /*
- * Don't clear pending XMIT flag here. Wait until we send so
- * we can detect if we dropped this message or not.
- */
- set_state_prl_tx(port, PRL_TX_SNK_PENDING);
- }
-}
-#endif /* CONFIG_USB_PD_REV30 */
-
-/*
- * PrlTxLayerResetForTransmit
- */
-static void prl_tx_layer_reset_for_transmit_entry(const int port)
-{
- print_current_prl_tx_state(port);
-
- if (pdmsg[port].xmit_type < NUM_SOP_STAR_TYPES) {
- /*
- * This state is only used during soft resets. Reset only the
- * matching message type.
- *
- * From section 6.3.13 Soft Reset Message in the USB PD 3.0
- * v2.0 spec, Soft_Reset Message Shall be targeted at a
- * specific entity depending on the type of SOP* Packet used.
- */
- prl_tx[port].msg_id_counter[pdmsg[port].xmit_type] = 0;
-
- /*
- * From section 6.11.2.3.2, the MessageID should be cleared
- * from the PRL_Rx_Layer_Reset_for_Receive state. However, we
- * don't implement a full state machine for PRL RX states so
- * clear the MessageID here.
- */
- prl_rx[port].msg_id[pdmsg[port].xmit_type] = -1;
- }
-}
-
-static void prl_tx_layer_reset_for_transmit_run(const int port)
-{
- /* NOTE: PRL_Tx_Construct_Message State embedded here */
- prl_tx_construct_message(port);
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_PHY_RESPONSE);
-}
-
-static uint32_t get_sop_star_header(const int port)
-{
- const int is_sop_packet = pdmsg[port].xmit_type == TCPCI_MSG_SOP;
- int ext;
-
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- ext = pdmsg[port].ext;
-#else
- ext = 0;
-#endif
-
- /* SOP vs SOP'/SOP" headers are different. Replace fields as needed */
- return PD_HEADER(
- pdmsg[port].msg_type,
- is_sop_packet ?
- pd_get_power_role(port) : tc_get_cable_plug(port),
- is_sop_packet ?
- pd_get_data_role(port) : 0,
- prl_tx[port].msg_id_counter[pdmsg[port].xmit_type],
- pdmsg[port].data_objs,
- pdmsg[port].rev[pdmsg[port].xmit_type],
- ext);
-}
-
-static void prl_tx_construct_message(const int port)
-{
- /* The header is unused for hard reset, etc. */
- const uint32_t header = pdmsg[port].xmit_type < NUM_SOP_STAR_TYPES ?
- get_sop_star_header(port) : 0;
-
- /* Save SOP* so the correct msg_id_counter can be incremented */
- prl_tx[port].last_xmit_type = pdmsg[port].xmit_type;
-
- /* Indicate that a tx message is being passed to the phy layer */
- prl_tx[port].xmit_status = TCPC_TX_WAIT;
- /*
- * PRL_FLAGS_TX_COMPLETE could be set if this function is called before
- * the Policy Engine is informed of the previous transmission. Clear the
- * flag so that this message can be sent.
- */
- PDMSG_CLR_FLAG(port, PRL_FLAGS_TX_COMPLETE);
-
- /*
- * Pass message to PHY Layer. It handles retries in hardware as the EC
- * cannot handle the required timing ~ 1ms (tReceive + tRetry).
- *
- * Note if we ever start sending large, extendend messages, then we
- * should not retry those messages. We do not support that and probably
- * never will (since we support chunking).
- */
- tcpm_transmit(port, pdmsg[port].xmit_type, header,
- pdmsg[port].tx_chk_buf);
-}
-
-/*
- * PrlTxWaitForPhyResponse
- */
-static void prl_tx_wait_for_phy_response_entry(const int port)
-{
- print_current_prl_tx_state(port);
-
- pd_timer_enable(port, PR_TIMER_TCPC_TX_TIMEOUT, PD_T_TCPC_TX_TIMEOUT);
-}
-
-static void prl_tx_wait_for_phy_response_run(const int port)
-{
- /* Wait until TX is complete */
-
- /*
- * NOTE: The TCPC will set xmit_status to TCPC_TX_COMPLETE_DISCARDED
- * when a GoodCRC containing an incorrect MessageID is received.
- * This condition satisfies the PRL_Tx_Match_MessageID state
- * requirement.
- */
-
- if (prl_tx[port].xmit_status == TCPC_TX_COMPLETE_SUCCESS) {
- /* NOTE: PRL_TX_Message_Sent State embedded here. */
- /* Increment messageId counter */
- increment_msgid_counter(port);
-
- /* Inform Policy Engine Message was sent */
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES))
- PDMSG_SET_FLAG(port, PRL_FLAGS_TX_COMPLETE);
- else
- pe_message_sent(port);
-
- /*
- * This event reduces the time of informing the policy engine of
- * the transmission by one state machine cycle
- */
- task_wake(PD_PORT_TO_TASK_ID(port));
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_MESSAGE_REQUEST);
- } else if (pd_timer_is_expired(port, PR_TIMER_TCPC_TX_TIMEOUT) ||
- prl_tx[port].xmit_status == TCPC_TX_COMPLETE_FAILED) {
- /*
- * NOTE: PRL_Tx_Transmission_Error State embedded
- * here.
- */
-
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) {
- /*
- * State tch_wait_for_transmission_complete will
- * inform policy engine of error
- */
- PDMSG_SET_FLAG(port, PRL_FLAGS_TX_ERROR);
- } else {
- /* Report Error To Policy Engine */
- pe_report_error(port, ERR_TCH_XMIT,
- prl_tx[port].last_xmit_type);
- }
-
- /* Increment message id counter */
- increment_msgid_counter(port);
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_MESSAGE_REQUEST);
- }
-}
-
-static void prl_tx_wait_for_phy_response_exit(const int port)
-{
- pd_timer_disable(port, PR_TIMER_TCPC_TX_TIMEOUT);
-}
-
-/* Source Protocol Layer Message Transmission */
-/*
- * PrlTxSrcPending
- */
-static void prl_tx_src_pending_entry(const int port)
-{
- print_current_prl_tx_state(port);
-
- /* Start SinkTxTimer */
- pd_timer_enable(port, PR_TIMER_SINK_TX, PD_T_SINK_TX);
-}
-
-static void prl_tx_src_pending_run(const int port)
-{
- if (pd_timer_is_expired(port, PR_TIMER_SINK_TX)) {
- /*
- * We clear the pending XMIT flag here right before we send so
- * we can detect if we discarded this message or not
- */
- PRL_TX_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT);
-
- /*
- * Soft Reset Message pending &
- * SinkTxTimer timeout
- */
- if ((tx_emsg[port].len == 0) &&
- (pdmsg[port].msg_type == PD_CTRL_SOFT_RESET)) {
- set_state_prl_tx(port, PRL_TX_LAYER_RESET_FOR_TRANSMIT);
- }
- /* Message pending (except Soft Reset) &
- * SinkTxTimer timeout
- */
- else {
- prl_tx_construct_message(port);
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_PHY_RESPONSE);
- }
-
- return;
- }
-}
-
-static void prl_tx_src_pending_exit(int port)
-{
- pd_timer_disable(port, PR_TIMER_SINK_TX);
-}
-
-/*
- * PrlTxSnkPending
- */
-static void prl_tx_snk_pending_entry(const int port)
-{
- print_current_prl_tx_state(port);
-}
-
-static void prl_tx_snk_pending_run(const int port)
-{
- bool start_tx = false;
-
- /*
- * Wait unit the SRC applies SINK_TX_OK so we can transmit. In FRS mode,
- * don't wait for SINK_TX_OK since either the source (and Rp) could be
- * gone or the TCPC CC_STATUS update time could be too long to meet
- * tFRSwapInit.
- */
- if (pe_in_frs_mode(port)) {
- /* shortcut to save some i2c_xfer calls on the FRS path. */
- start_tx = true;
- } else {
- enum tcpc_cc_voltage_status cc1, cc2;
-
- tcpm_get_cc(port, &cc1, &cc2);
- start_tx = (cc1 == TYPEC_CC_VOLT_RP_3_0 ||
- cc2 == TYPEC_CC_VOLT_RP_3_0);
- }
- if (start_tx) {
- /*
- * We clear the pending XMIT flag here right before we send so
- * we can detect if we discarded this message or not
- */
- PRL_TX_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT);
-
- /*
- * Soft Reset Message Message pending &
- * Rp = SinkTxOk
- */
- if ((pdmsg[port].msg_type == PD_CTRL_SOFT_RESET) &&
- (tx_emsg[port].len == 0)) {
- set_state_prl_tx(port, PRL_TX_LAYER_RESET_FOR_TRANSMIT);
- }
- /*
- * Message pending (except Soft Reset) &
- * Rp = SinkTxOk
- */
- else {
- prl_tx_construct_message(port);
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_PHY_RESPONSE);
- }
- return;
- }
-}
-
-/* Hard Reset Operation */
-void prl_hr_send_msg_to_phy(const int port)
-{
- /* Header is not used for hard reset */
- const uint32_t header = 0;
-
- pdmsg[port].xmit_type = TCPCI_MSG_TX_HARD_RESET;
-
- /*
- * These flags could be set if this function is called before the
- * Policy Engine is informed of the previous transmission. Clear the
- * flags so that this message can be sent.
- */
- prl_tx[port].xmit_status = TCPC_TX_UNSET;
- PDMSG_CLR_FLAG(port, PRL_FLAGS_TX_COMPLETE);
-
- /* Pass message to PHY Layer */
- tcpm_transmit(port, pdmsg[port].xmit_type, header,
- pdmsg[port].tx_chk_buf);
-}
-
-static void prl_hr_wait_for_request_entry(const int port)
-{
- print_current_prl_hr_state(port);
-
- prl_hr[port].flags = 0;
-}
-
-static void prl_hr_wait_for_request_run(const int port)
-{
- if (PRL_HR_CHK_FLAG(port, PRL_FLAGS_PE_HARD_RESET |
- PRL_FLAGS_PORT_PARTNER_HARD_RESET))
- set_state_prl_hr(port, PRL_HR_RESET_LAYER);
-}
-
-/*
- * PrlHrResetLayer
- */
-static void prl_hr_reset_layer_entry(const int port)
-{
- int i;
-
- print_current_prl_hr_state(port);
-
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) {
- tch[port].flags = 0;
- rch[port].flags = 0;
- }
-
- pdmsg[port].flags = 0;
-
- /* Hard reset resets messageIDCounters for all TX types */
- for (i = 0; i < NUM_SOP_STAR_TYPES; i++) {
- prl_rx[port].msg_id[i] = -1;
- prl_tx[port].msg_id_counter[i] = 0;
- }
-
- /* Disable RX */
- if (IS_ENABLED(CONFIG_USB_CTVPD) ||
- IS_ENABLED(CONFIG_USB_VPD))
- vpd_rx_enable(0);
- else
- tcpm_set_rx_enable(port, 0);
-
- /*
- * PD r3.0 v2.0, ss6.2.1.1.5:
- * After a physical or logical (USB Type-C Error Recovery) Attach, a
- * Port discovers the common Specification Revision level between itself
- * and its Port Partner and/or the Cable Plug(s), and uses this
- * Specification Revision level until a Detach, Hard Reset or Error
- * Recovery happens.
- *
- * This covers the Hard Reset case.
- */
- prl_set_default_pd_revision(port);
-
- /* Inform the AP of Hard Reset */
- if (IS_ENABLED(CONFIG_USB_PD_HOST_CMD))
- pd_notify_event(port, PD_STATUS_EVENT_HARD_RESET);
-
- /*
- * Protocol Layer message transmission transitions to
- * PRL_Tx_Wait_For_Message_Request state.
- */
- set_state_prl_tx(port, PRL_TX_WAIT_FOR_MESSAGE_REQUEST);
-
- return;
-}
-
-static void prl_hr_reset_layer_run(const int port)
-{
- /*
- * Protocol Layer reset Complete &
- * Hard Reset was initiated by Policy Engine
- */
- if (PRL_HR_CHK_FLAG(port, PRL_FLAGS_PE_HARD_RESET)) {
- /*
- * Request PHY to perform a Hard Reset. Note
- * PRL_HR_Request_Reset state is embedded here.
- */
- prl_hr_send_msg_to_phy(port);
- set_state_prl_hr(port, PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE);
- }
- /*
- * Protocol Layer reset complete &
- * Hard Reset was initiated by Port Partner
- */
- else {
- /* Inform Policy Engine of the Hard Reset */
- pe_got_hard_reset(port);
- set_state_prl_hr(port, PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE);
- }
-}
-
-/*
- * PrlHrWaitForPhyHardResetComplete
- */
-static void prl_hr_wait_for_phy_hard_reset_complete_entry(const int port)
-{
- print_current_prl_hr_state(port);
-
- /* Start HardResetCompleteTimer */
- pd_timer_enable(port, PR_TIMER_HARD_RESET_COMPLETE,
- PD_T_PS_HARD_RESET);
-}
-
-static void prl_hr_wait_for_phy_hard_reset_complete_run(const int port)
-{
- /*
- * Wait for hard reset from PHY
- * or timeout
- */
- if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_COMPLETE) ||
- pd_timer_is_expired(port, PR_TIMER_HARD_RESET_COMPLETE)) {
- /* PRL_HR_PHY_Hard_Reset_Requested */
-
- /* Inform Policy Engine Hard Reset was sent */
- pe_hard_reset_sent(port);
- set_state_prl_hr(port, PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE);
-
- return;
- }
-}
-
-static void prl_hr_wait_for_phy_hard_reset_complete_exit(int port)
-{
- pd_timer_disable(port, PR_TIMER_HARD_RESET_COMPLETE);
-}
-
-/*
- * PrlHrWaitForPeHardResetComplete
- */
-static void prl_hr_wait_for_pe_hard_reset_complete_entry(const int port)
-{
- print_current_prl_hr_state(port);
-}
-
-static void prl_hr_wait_for_pe_hard_reset_complete_run(const int port)
-{
- /*
- * Wait for Hard Reset complete indication from Policy Engine
- */
- if (PRL_HR_CHK_FLAG(port, PRL_FLAGS_HARD_RESET_COMPLETE))
- set_state_prl_hr(port, PRL_HR_WAIT_FOR_REQUEST);
-}
-
-static void prl_hr_wait_for_pe_hard_reset_complete_exit(const int port)
-{
- /* Exit from Hard Reset */
-
- set_state_prl_tx(port, PRL_TX_PHY_LAYER_RESET);
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) {
- set_state_rch(port, RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER);
- set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
- }
-}
-
-static void copy_chunk_to_ext(int port)
-{
- /* Calculate number of bytes */
- pdmsg[port].num_bytes_received =
- (PD_HEADER_CNT(rx_emsg[port].header) * 4);
-
- /* Copy chunk into extended message */
- memcpy((uint8_t *)rx_emsg[port].buf, (uint8_t *)pdmsg[port].rx_chk_buf,
- pdmsg[port].num_bytes_received);
-
- /* Set extended message length */
- rx_emsg[port].len = pdmsg[port].num_bytes_received;
-}
-
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
-/*
- * Chunked Rx State Machine
- */
-/*
- * RchWaitForMessageFromProtocolLayer
- */
-static void rch_wait_for_message_from_protocol_layer_entry(const int port)
-{
- print_current_rch_state(port);
-
- /* Clear Abort flag */
- PDMSG_CLR_FLAG(port, PRL_FLAGS_ABORT);
-
- /* All Messages are chunked */
- rch[port].flags = PRL_FLAGS_CHUNKING;
-}
-
-static void rch_wait_for_message_from_protocol_layer_run(const int port)
-{
- if (RCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- RCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- /*
- * Are we communicating with a PD3.0 device and is
- * this an extended message?
- */
- if (pdmsg_xmit_type_is_rev30(port)
- && PD_HEADER_EXT(rx_emsg[port].header)) {
- uint16_t exhdr =
- GET_EXT_HEADER(*pdmsg[port].rx_chk_buf);
- uint8_t chunked = PD_EXT_HEADER_CHUNKED(exhdr);
-
- /*
- * Received Extended Message &
- * (Chunking = 1 & Chunked = 1)
- */
- if ((RCH_CHK_FLAG(port, PRL_FLAGS_CHUNKING)) &&
- chunked) {
- /*
- * RCH_Processing_Extended_Message first chunk
- * entry processing embedded here
- *
- * This is the first chunk:
- * Set Chunk_number_expected = 0 and
- * Num_Bytes_Received = 0
- */
- pdmsg[port].chunk_number_expected = 0;
- pdmsg[port].num_bytes_received = 0;
- pdmsg[port].msg_type =
- PD_HEADER_TYPE(rx_emsg[port].header);
-
- set_state_rch(port,
- RCH_PROCESSING_EXTENDED_MESSAGE);
- }
- /*
- * (Received Extended Message &
- * (Chunking = 0 & Chunked = 0))
- */
- else if (!RCH_CHK_FLAG(port, PRL_FLAGS_CHUNKING) &&
- !chunked) {
- /* Copy chunk to extended buffer */
- copy_chunk_to_ext(port);
- set_state_rch(port, RCH_PASS_UP_MESSAGE);
- }
- /*
- * Chunked != Chunking
- */
- else {
- rch[port].error = ERR_RCH_CHUNKED;
- set_state_rch(port, RCH_REPORT_ERROR);
- }
- }
- /*
- * Received Non-Extended Message
- */
- else if (!PD_HEADER_EXT(rx_emsg[port].header)) {
- /* Copy chunk to extended buffer */
- copy_chunk_to_ext(port);
- set_state_rch(port, RCH_PASS_UP_MESSAGE);
- }
- /*
- * Received an Extended Message while communicating at a
- * revision lower than PD3.0
- */
- else {
- rch[port].error = ERR_RCH_CHUNKED;
- set_state_rch(port, RCH_REPORT_ERROR);
- }
- }
-}
-
-/*
- * RchPassUpMessage
- */
-static void rch_pass_up_message_entry(const int port)
-{
- print_current_rch_state(port);
-
- /* Pass Message to Policy Engine */
- pe_message_received(port);
- set_state_rch(port, RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER);
-}
-
-/*
- * RchProcessingExtendedMessage
- */
-static void rch_processing_extended_message_entry(const int port)
-{
- print_current_rch_state(port);
-}
-
-static void rch_processing_extended_message_run(const int port)
-{
- uint16_t exhdr = GET_EXT_HEADER(pdmsg[port].rx_chk_buf[0]);
- uint8_t chunk_num = PD_EXT_HEADER_CHUNK_NUM(exhdr);
- uint32_t data_size = PD_EXT_HEADER_DATA_SIZE(exhdr);
- uint32_t byte_num;
-
- /*
- * Abort Flag Set
- */
- if (PDMSG_CHK_FLAG(port, PRL_FLAGS_ABORT))
- set_state_rch(port, RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER);
-
- /*
- * If expected Chunk Number:
- * Append data to Extended_Message_Buffer
- * Increment Chunk_number_Expected
- * Adjust Num Bytes Received
- */
- else if (chunk_num == pdmsg[port].chunk_number_expected) {
- byte_num = data_size - pdmsg[port].num_bytes_received;
-
- if (byte_num >= PD_MAX_EXTENDED_MSG_CHUNK_LEN)
- byte_num = PD_MAX_EXTENDED_MSG_CHUNK_LEN;
-
- /* Make sure extended message buffer does not overflow */
- if (pdmsg[port].num_bytes_received +
- byte_num > EXTENDED_BUFFER_SIZE) {
- rch[port].error = ERR_RCH_CHUNKED;
- set_state_rch(port, RCH_REPORT_ERROR);
- return;
- }
-
- /* Append data */
- /* Add 2 to chk_buf to skip over extended message header */
- memcpy(((uint8_t *)rx_emsg[port].buf +
- pdmsg[port].num_bytes_received),
- (uint8_t *)pdmsg[port].rx_chk_buf + 2,
- byte_num);
- /* increment chunk number expected */
- pdmsg[port].chunk_number_expected++;
- /* adjust num bytes received */
- pdmsg[port].num_bytes_received += byte_num;
-
- /* Was that the last chunk? */
- if (pdmsg[port].num_bytes_received >= data_size) {
- rx_emsg[port].len = pdmsg[port].num_bytes_received;
- /* Pass Message to Policy Engine */
- set_state_rch(port, RCH_PASS_UP_MESSAGE);
- }
- /*
- * Message not Complete
- */
- else
- set_state_rch(port, RCH_REQUESTING_CHUNK);
- }
- /*
- * Unexpected Chunk Number
- */
- else {
- rch[port].error = ERR_RCH_CHUNKED;
- set_state_rch(port, RCH_REPORT_ERROR);
- }
-}
-
-/*
- * RchRequestingChunk
- */
-static void rch_requesting_chunk_entry(const int port)
-{
- print_current_rch_state(port);
-
- /*
- * Send Chunk Request to Protocol Layer
- * with chunk number = Chunk_Number_Expected
- */
- pdmsg[port].tx_chk_buf[0] = PD_EXT_HEADER(
- pdmsg[port].chunk_number_expected,
- 1, /* Request Chunk */
- 0 /* Data Size */
- );
-
- pdmsg[port].data_objs = 1;
- pdmsg[port].ext = 1;
- pdmsg[port].xmit_type = prl_rx[port].sop;
- PRL_TX_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TX);
-}
-
-static void rch_requesting_chunk_run(const int port)
-{
- /*
- * Message Transmitted received from Protocol Layer
- */
- if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_COMPLETE)) {
- PDMSG_CLR_FLAG(port, PRL_FLAGS_TX_COMPLETE);
- set_state_rch(port, RCH_WAITING_CHUNK);
- } else if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_ERROR)) {
- /* Transmission Error from Protocol Layer detetected */
- rch[port].error = ERR_RCH_CHUNKED;
- set_state_rch(port, RCH_REPORT_ERROR);
- } else if (RCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- /*
- * It is possible to have both message received and the chunk
- * request transmit complete before a full PRL SM run. But, the
- * PRL_RX state machine runs prior to RCH, but before PRL_TX, so
- * PRL_FLAGS_MSG_RECEIVED can be set without
- * PRL_FLAGS_TX_COMPLETE set at this point (though it will be
- * set as soon as PRL_TX is executed next.
- */
- set_state_rch(port, RCH_WAITING_CHUNK);
- }
-}
-
-/*
- * RchWaitingChunk
- */
-static void rch_waiting_chunk_entry(const int port)
-{
- print_current_rch_state(port);
-
- /*
- * Start ChunkSenderResponseTimer
- */
- pd_timer_enable(port, PR_TIMER_CHUNK_SENDER_RESPONSE,
- PD_T_CHUNK_SENDER_RESPONSE);
-}
-
-static void rch_waiting_chunk_run(const int port)
-{
- if (RCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- /*
- * Because of the 5 msec tick time, it is possible to have both
- * msg_received and tx_complete flags set for a given PRL sm
- * run. Since prl_rx runs prior to the tx state machines, clear
- * the tx_complete flag as the next chunk has already been
- * received.
- */
- if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_COMPLETE))
- PDMSG_CLR_FLAG(port, PRL_FLAGS_TX_COMPLETE);
-
- /*
- * Leave PRL_FLAGS_MSG_RECEIVED flag set just in case an error
- * is detected. If an error is detected, PRL_FLAGS_MSG_RECEIVED
- * will be cleared in rch_report_error state.
- */
-
- if (PD_HEADER_EXT(rx_emsg[port].header)) {
- uint16_t exhdr =
- GET_EXT_HEADER(pdmsg[port].rx_chk_buf[0]);
- /*
- * Other Message Received from Protocol Layer
- */
- if (PD_EXT_HEADER_REQ_CHUNK(exhdr) ||
- !PD_EXT_HEADER_CHUNKED(exhdr)) {
- rch[port].error = ERR_RCH_CHUNKED;
- set_state_rch(port, RCH_REPORT_ERROR);
- }
- /*
- * Chunk response Received from Protocol Layer
- */
- else {
- /*
- * No error was detected, so clear
- * PRL_FLAGS_MSG_RECEIVED flag.
- */
- RCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- set_state_rch(port,
- RCH_PROCESSING_EXTENDED_MESSAGE);
- }
- }
- }
- /*
- * ChunkSenderResponseTimer Timeout
- */
- else if (pd_timer_is_expired(port, PR_TIMER_CHUNK_SENDER_RESPONSE)) {
- rch[port].error = ERR_RCH_CHUNK_WAIT_TIMEOUT;
- set_state_rch(port, RCH_REPORT_ERROR);
- }
-}
-
-static void rch_waiting_chunk_exit(int port)
-{
- pd_timer_disable(port, PR_TIMER_CHUNK_SENDER_RESPONSE);
-}
-
-/*
- * RchReportError
- */
-static void rch_report_error_entry(const int port)
-{
- print_current_rch_state(port);
-
- /*
- * If the state was entered because a message was received,
- * this message is passed to the Policy Engine.
- */
- if (RCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- RCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
-
- /* Copy chunk to extended buffer */
- copy_chunk_to_ext(port);
- /* Pass Message to Policy Engine */
- pe_message_received(port);
- /* Report error */
- pe_report_error(port, ERR_RCH_MSG_REC, prl_rx[port].sop);
- } else {
- pe_report_error(port, rch[port].error, prl_rx[port].sop);
- }
-}
-
-static void rch_report_error_run(const int port)
-{
- set_state_rch(port, RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER);
-}
-
-/*
- * Chunked Tx State Machine
- */
-
-/*
- * TchWaitForMessageRequestFromPe
- */
-static void tch_wait_for_message_request_from_pe_entry(const int port)
-{
- print_current_tch_state(port);
-
- /* Clear Abort flag */
- PDMSG_CLR_FLAG(port, PRL_FLAGS_ABORT);
-
- /* All Messages are chunked */
- tch[port].flags = PRL_FLAGS_CHUNKING;
-}
-
-static void tch_wait_for_message_request_from_pe_run(const int port)
-{
- /*
- * Any message received and not in state TCH_Wait_Chunk_Request
- */
- if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- set_state_tch(port, TCH_MESSAGE_RECEIVED);
- } else if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT);
- /*
- * Rx Chunking State != RCH_Wait_For_Message_From_Protocol_Layer
- * & Abort Supported
- *
- * Discard the Message
- */
- if (rch_get_state(port) !=
- RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER) {
- tch[port].error = ERR_TCH_XMIT;
- set_state_tch(port, TCH_REPORT_ERROR);
- } else {
- /*
- * Extended Message Request & Chunking
- */
- if (pdmsg_xmit_type_is_rev30(port)
- && pdmsg[port].ext
- && TCH_CHK_FLAG(port, PRL_FLAGS_CHUNKING)) {
- /*
- * NOTE: TCH_Prepare_To_Send_Chunked_Message
- * embedded here.
- */
- pdmsg[port].send_offset = 0;
- pdmsg[port].chunk_number_to_send = 0;
- set_state_tch(port,
- TCH_CONSTRUCT_CHUNKED_MESSAGE);
- } else
- /*
- * Non-Extended Message Request
- */
- {
- /* NOTE: TCH_Pass_Down_Message embedded here */
- prl_copy_msg_to_buffer(port);
-
- /* Pass Message to Protocol Layer */
- PRL_TX_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
- set_state_tch(port,
- TCH_WAIT_FOR_TRANSMISSION_COMPLETE);
- }
- }
- }
-}
-
-/*
- * TchWaitForTransmissionComplete
- */
-static void tch_wait_for_transmission_complete_entry(const int port)
-{
- print_current_tch_state(port);
-}
-
-static void tch_wait_for_transmission_complete_run(const int port)
-{
- /*
- * Inform Policy Engine that Message was sent.
- */
- if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_COMPLETE)) {
- PDMSG_CLR_FLAG(port, PRL_FLAGS_TX_COMPLETE);
- set_state_tch(port, TCH_MESSAGE_SENT);
- return;
- }
- /*
- * Inform Policy Engine of Tx Error
- */
- else if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_ERROR)) {
- PDMSG_CLR_FLAG(port, PRL_FLAGS_TX_ERROR);
- tch[port].error = ERR_TCH_XMIT;
- set_state_tch(port, TCH_REPORT_ERROR);
- return;
- }
- /*
- * A message was received while TCH is waiting for the phy to complete
- * sending a tx message.
- *
- * Because of our prl_sm architecture and I2C access delays for TCPCs,
- * it's possible to have a message received and the prl_tx state not be
- * in its default waiting state. To avoid a false protocol error, only
- * jump to TCH_MESSAGE_RECEIVED if the phy layer has not indicated that
- * the tx message was sent successfully.
- */
- if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED) &&
- prl_tx[port].xmit_status != TCPC_TX_COMPLETE_SUCCESS) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- set_state_tch(port, TCH_MESSAGE_RECEIVED);
- return;
- }
-}
-
-/*
- * TchConstructChunkedMessage
- */
-static void tch_construct_chunked_message_entry(const int port)
-{
- uint16_t *ext_hdr;
- uint8_t *data;
- uint16_t num;
-
- print_current_tch_state(port);
-
- /*
- * Any message received and not in state TCH_Wait_Chunk_Request
- */
- if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- set_state_tch(port, TCH_MESSAGE_RECEIVED);
- return;
- }
-
- /* Prepare to copy chunk into chk_buf */
-
- ext_hdr = (uint16_t *)pdmsg[port].tx_chk_buf;
- data = ((uint8_t *)pdmsg[port].tx_chk_buf + 2);
- num = tx_emsg[port].len - pdmsg[port].send_offset;
-
- if (num > PD_MAX_EXTENDED_MSG_CHUNK_LEN)
- num = PD_MAX_EXTENDED_MSG_CHUNK_LEN;
-
- /* Set the chunks extended header */
- *ext_hdr = PD_EXT_HEADER(pdmsg[port].chunk_number_to_send,
- 0, /* Chunk Request */
- tx_emsg[port].len);
-
- /* Copy the message chunk into chk_buf */
- memset(data, 0, 28);
- memcpy(data, tx_emsg[port].buf + pdmsg[port].send_offset, num);
- pdmsg[port].send_offset += num;
-
- /*
- * Add in 2 bytes for extended header
- * pad out to 4-byte boundary
- * convert to number of 4-byte words
- * Since the value is shifted right by 2,
- * no need to explicitly clear the lower
- * 2-bits.
- */
- pdmsg[port].data_objs = (num + 2 + 3) >> 2;
-
- /* Pass message chunk to Protocol Layer */
- PRL_TX_SET_FLAG(port, PRL_FLAGS_MSG_XMIT);
-}
-
-static void tch_construct_chunked_message_run(const int port)
-{
- if (PDMSG_CHK_FLAG(port, PRL_FLAGS_ABORT))
- set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
- else
- set_state_tch(port, TCH_SENDING_CHUNKED_MESSAGE);
-}
-
-/*
- * TchSendingChunkedMessage
- */
-static void tch_sending_chunked_message_entry(const int port)
-{
- print_current_tch_state(port);
-}
-
-static void tch_sending_chunked_message_run(const int port)
-{
- /*
- * Transmission Error
- */
- if (PDMSG_CHK_FLAG(port, PRL_FLAGS_TX_ERROR)) {
- tch[port].error = ERR_TCH_XMIT;
- set_state_tch(port, TCH_REPORT_ERROR);
- }
- /*
- * Message Transmitted from Protocol Layer &
- * Last Chunk
- */
- else if (tx_emsg[port].len == pdmsg[port].send_offset)
- set_state_tch(port, TCH_MESSAGE_SENT);
- /*
- * Any message received and not in state TCH_Wait_Chunk_Request
- */
- else if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- set_state_tch(port, TCH_MESSAGE_RECEIVED);
- }
- /*
- * Message Transmitted from Protocol Layer &
- * Not Last Chunk
- */
- else
- set_state_tch(port, TCH_WAIT_CHUNK_REQUEST);
-}
-
-/*
- * TchWaitChunkRequest
- */
-static void tch_wait_chunk_request_entry(const int port)
-{
- print_current_tch_state(port);
-
- /* Increment Chunk Number to Send */
- pdmsg[port].chunk_number_to_send++;
- /* Start Chunk Sender Request Timer */
- pd_timer_enable(port, PR_TIMER_CHUNK_SENDER_REQUEST,
- PD_T_CHUNK_SENDER_REQUEST);
-}
-
-static void tch_wait_chunk_request_run(const int port)
-{
- if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
-
- if (PD_HEADER_EXT(rx_emsg[port].header)) {
- uint16_t exthdr;
-
- exthdr = GET_EXT_HEADER(pdmsg[port].rx_chk_buf[0]);
- if (PD_EXT_HEADER_REQ_CHUNK(exthdr)) {
- /*
- * Chunk Request Received &
- * Chunk Number = Chunk Number to Send
- */
- if (PD_EXT_HEADER_CHUNK_NUM(exthdr) ==
- pdmsg[port].chunk_number_to_send) {
- set_state_tch(port,
- TCH_CONSTRUCT_CHUNKED_MESSAGE);
- }
- /*
- * Chunk Request Received &
- * Chunk Number != Chunk Number to Send
- */
- else {
- tch[port].error = ERR_TCH_CHUNKED;
- set_state_tch(port, TCH_REPORT_ERROR);
- }
- return;
- }
- }
-
- /*
- * Other message received
- */
- set_state_tch(port, TCH_MESSAGE_RECEIVED);
- }
- /*
- * ChunkSenderRequestTimer timeout
- */
- else if (pd_timer_is_expired(port, PR_TIMER_CHUNK_SENDER_REQUEST))
- set_state_tch(port, TCH_MESSAGE_SENT);
-}
-
-static void tch_wait_chunk_request_exit(int port)
-{
- pd_timer_disable(port, PR_TIMER_CHUNK_SENDER_REQUEST);
-}
-
-/*
- * TchMessageReceived
- */
-static void tch_message_received_entry(const int port)
-{
- print_current_tch_state(port);
-
- /* Pass message to chunked Rx */
- RCH_SET_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
-
- /* Clear extended message objects */
- if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_XMIT);
- pe_report_discard(port);
- }
- pdmsg[port].data_objs = 0;
-}
-
-static void tch_message_received_run(const int port)
-{
- set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
-}
-
-/*
- * TchMessageSent
- */
-static void tch_message_sent_entry(const int port)
-{
- print_current_tch_state(port);
-
- /* Tell PE message was sent */
- pe_message_sent(port);
-
- /*
- * Any message received and not in state TCH_Wait_Chunk_Request
- * MUST be checked after notifying PE
- */
- if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- set_state_tch(port, TCH_MESSAGE_RECEIVED);
- return;
- }
-
-
-
- set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
-}
-
-/*
- * TchReportError
- */
-static void tch_report_error_entry(const int port)
-{
- print_current_tch_state(port);
-
- /* Report Error To Policy Engine */
- pe_report_error(port, tch[port].error, prl_tx[port].last_xmit_type);
-
- /*
- * Any message received and not in state TCH_Wait_Chunk_Request
- * MUST be checked after notifying PE
- */
- if (TCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED)) {
- TCH_CLR_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- set_state_tch(port, TCH_MESSAGE_RECEIVED);
- return;
- }
-
-
- set_state_tch(port, TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
-}
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-
-/*
- * Protocol Layer Message Reception State Machine
- */
-static void prl_rx_wait_for_phy_message(const int port, int evt)
-{
- uint32_t header;
- uint8_t type;
- uint8_t cnt;
- int8_t msid;
-
- /*
- * If PD3, wait for the RX chunk SM to copy the pdmsg into the extended
- * buffer before overwriting pdmsg.
- */
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES) &&
- RCH_CHK_FLAG(port, PRL_FLAGS_MSG_RECEIVED))
- return;
-
- /* If we don't have any message, just stop processing now. */
- if (!tcpm_has_pending_message(port) ||
- tcpm_dequeue_message(port, pdmsg[port].rx_chk_buf, &header))
- return;
-
- rx_emsg[port].header = header;
- type = PD_HEADER_TYPE(header);
- cnt = PD_HEADER_CNT(header);
- msid = PD_HEADER_ID(header);
- prl_rx[port].sop = PD_HEADER_GET_SOP(header);
-
- /* Make sure an incorrect count doesn't overflow the chunk buffer */
- if (cnt > CHK_BUF_SIZE)
- cnt = CHK_BUF_SIZE;
-
- /* dump received packet content (only dump ping at debug level MAX) */
- if ((prl_debug_level >= DEBUG_LEVEL_2 && type != PD_CTRL_PING) ||
- prl_debug_level >= DEBUG_LEVEL_3) {
- int p;
-
- ccprintf("C%d: RECV %04x/%d ", port, header, cnt);
- for (p = 0; p < cnt; p++)
- ccprintf("[%d]%08x ", p, pdmsg[port].rx_chk_buf[p]);
- ccprintf("\n");
- }
-
- /*
- * Ignore messages sent to the cable from our
- * port partner if we aren't Vconn powered device.
- */
- if (!IS_ENABLED(CONFIG_USB_CTVPD) &&
- !IS_ENABLED(CONFIG_USB_VPD) &&
- PD_HEADER_GET_SOP(header) != TCPCI_MSG_SOP &&
- PD_HEADER_PROLE(header) == PD_PLUG_FROM_DFP_UFP)
- return;
-
- /* Handle incoming soft reset as special case */
- if (cnt == 0 && type == PD_CTRL_SOFT_RESET) {
- /* Clear MessageIdCounter */
- prl_tx[port].msg_id_counter[prl_rx[port].sop] = 0;
- /* Clear stored MessageID value */
- prl_rx[port].msg_id[prl_rx[port].sop] = -1;
-
- /* Soft Reset occurred */
- set_state_prl_tx(port, PRL_TX_PHY_LAYER_RESET);
-
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) {
- set_state_rch(port,
- RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER);
- set_state_tch(port,
- TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE);
- }
-
- /*
- * Inform Policy Engine of Soft Reset. Note perform this after
- * performing the protocol layer reset, otherwise we will lose
- * the PE's outgoing ACCEPT message to the soft reset.
- */
- pe_got_soft_reset(port);
-
- return;
- }
-
- /*
- * Ignore if this is a duplicate message. Stop processing.
- */
- if (prl_rx[port].msg_id[prl_rx[port].sop] == msid)
- return;
-
- /*
- * Discard any pending tx message if this is
- * not a ping message (length must be checked to verify this is a
- * control message, rather than data)
- */
- if ((cnt > 0) || (type != PD_CTRL_PING)) {
- /*
- * Note: Spec dictates that we always go into
- * PRL_Tx_Discard_Message upon receivng a message. However, due
- * to our TCPC architecture we may be receiving a transmit
- * complete at the same time as a response so only do this if a
- * message is pending.
- */
- if (prl_tx[port].xmit_status != TCPC_TX_COMPLETE_SUCCESS ||
- PRL_TX_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT))
- set_state_prl_tx(port, PRL_TX_DISCARD_MESSAGE);
- }
-
- /* Store Message Id */
- prl_rx[port].msg_id[prl_rx[port].sop] = msid;
-
- if (IS_ENABLED(CONFIG_USB_PD_EXTENDED_MESSAGES)) {
- /* RTR Chunked Message Router States. */
- /*
- * Received Ping from Protocol Layer
- */
- if (cnt == 0 && type == PD_CTRL_PING) {
- /* NOTE: RTR_PING State embedded here. */
- rx_emsg[port].len = 0;
- pe_message_received(port);
- return;
- }
- /*
- * Message (not Ping) Received from
- * Protocol Layer & Doing Tx Chunks
- *
- * Also, handle the case where a message has been
- * queued for sending but a message is received before
- * tch_wait_for_message_request_from_pe has been run
- */
- else if (tch_get_state(port) !=
- TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE ||
- TCH_CHK_FLAG(port, PRL_FLAGS_MSG_XMIT)) {
- /* NOTE: RTR_TX_CHUNKS State embedded here. */
- /*
- * Send Message to Tx Chunk
- * Chunk State Machine
- */
- TCH_SET_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- }
- /*
- * Message (not Ping) Received from
- * Protocol Layer & Not Doing Tx Chunks
- */
- else {
- /* NOTE: RTR_RX_CHUNKS State embedded here. */
- /*
- * Send Message to Rx
- * Chunk State Machine
- */
- RCH_SET_FLAG(port, PRL_FLAGS_MSG_RECEIVED);
- }
- } else {
- /* Copy chunk to extended buffer */
- copy_chunk_to_ext(port);
- /* Send message to Policy Engine */
- pe_message_received(port);
- }
-
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-/* All necessary Protocol Transmit States (Section 6.11.2.2) */
-static __const_data const struct usb_state prl_tx_states[] = {
- [PRL_TX_PHY_LAYER_RESET] = {
- .entry = prl_tx_phy_layer_reset_entry,
- },
- [PRL_TX_WAIT_FOR_MESSAGE_REQUEST] = {
- .entry = prl_tx_wait_for_message_request_entry,
- .run = prl_tx_wait_for_message_request_run,
- },
- [PRL_TX_LAYER_RESET_FOR_TRANSMIT] = {
- .entry = prl_tx_layer_reset_for_transmit_entry,
- .run = prl_tx_layer_reset_for_transmit_run,
- },
- [PRL_TX_WAIT_FOR_PHY_RESPONSE] = {
- .entry = prl_tx_wait_for_phy_response_entry,
- .run = prl_tx_wait_for_phy_response_run,
- .exit = prl_tx_wait_for_phy_response_exit,
- },
-#ifdef CONFIG_USB_PD_REV30
- [PRL_TX_SRC_SOURCE_TX] = {
- .entry = prl_tx_src_source_tx_entry,
- .run = prl_tx_src_source_tx_run,
- },
- [PRL_TX_SNK_START_AMS] = {
- .entry = prl_tx_snk_start_ams_entry,
- .run = prl_tx_snk_start_ams_run,
- },
-#endif /* CONFIG_USB_PD_REV30 */
- [PRL_TX_SRC_PENDING] = {
- .entry = prl_tx_src_pending_entry,
- .run = prl_tx_src_pending_run,
- .exit = prl_tx_src_pending_exit,
- },
- [PRL_TX_SNK_PENDING] = {
- .entry = prl_tx_snk_pending_entry,
- .run = prl_tx_snk_pending_run,
- },
- [PRL_TX_DISCARD_MESSAGE] = {
- .entry = prl_tx_discard_message_entry,
- },
-};
-
-/* All necessary Protocol Hard Reset States (Section 6.11.2.4) */
-static __const_data const struct usb_state prl_hr_states[] = {
- [PRL_HR_WAIT_FOR_REQUEST] = {
- .entry = prl_hr_wait_for_request_entry,
- .run = prl_hr_wait_for_request_run,
- },
- [PRL_HR_RESET_LAYER] = {
- .entry = prl_hr_reset_layer_entry,
- .run = prl_hr_reset_layer_run,
- },
- [PRL_HR_WAIT_FOR_PHY_HARD_RESET_COMPLETE] = {
- .entry = prl_hr_wait_for_phy_hard_reset_complete_entry,
- .run = prl_hr_wait_for_phy_hard_reset_complete_run,
- .exit = prl_hr_wait_for_phy_hard_reset_complete_exit,
- },
- [PRL_HR_WAIT_FOR_PE_HARD_RESET_COMPLETE] = {
- .entry = prl_hr_wait_for_pe_hard_reset_complete_entry,
- .run = prl_hr_wait_for_pe_hard_reset_complete_run,
- .exit = prl_hr_wait_for_pe_hard_reset_complete_exit,
- },
-};
-
-/* All necessary Chunked Rx states (Section 6.11.2.1.2) */
-__maybe_unused static const struct usb_state rch_states[] = {
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- [RCH_WAIT_FOR_MESSAGE_FROM_PROTOCOL_LAYER] = {
- .entry = rch_wait_for_message_from_protocol_layer_entry,
- .run = rch_wait_for_message_from_protocol_layer_run,
- },
- [RCH_PASS_UP_MESSAGE] = {
- .entry = rch_pass_up_message_entry,
- },
- [RCH_PROCESSING_EXTENDED_MESSAGE] = {
- .entry = rch_processing_extended_message_entry,
- .run = rch_processing_extended_message_run,
- },
- [RCH_REQUESTING_CHUNK] = {
- .entry = rch_requesting_chunk_entry,
- .run = rch_requesting_chunk_run,
- },
- [RCH_WAITING_CHUNK] = {
- .entry = rch_waiting_chunk_entry,
- .run = rch_waiting_chunk_run,
- .exit = rch_waiting_chunk_exit,
- },
- [RCH_REPORT_ERROR] = {
- .entry = rch_report_error_entry,
- .run = rch_report_error_run,
- },
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-};
-
-/* All necessary Chunked Tx states (Section 6.11.2.1.3) */
-__maybe_unused static const struct usb_state tch_states[] = {
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- [TCH_WAIT_FOR_MESSAGE_REQUEST_FROM_PE] = {
- .entry = tch_wait_for_message_request_from_pe_entry,
- .run = tch_wait_for_message_request_from_pe_run,
- },
- [TCH_WAIT_FOR_TRANSMISSION_COMPLETE] = {
- .entry = tch_wait_for_transmission_complete_entry,
- .run = tch_wait_for_transmission_complete_run,
- },
- [TCH_CONSTRUCT_CHUNKED_MESSAGE] = {
- .entry = tch_construct_chunked_message_entry,
- .run = tch_construct_chunked_message_run,
- },
- [TCH_SENDING_CHUNKED_MESSAGE] = {
- .entry = tch_sending_chunked_message_entry,
- .run = tch_sending_chunked_message_run,
- },
- [TCH_WAIT_CHUNK_REQUEST] = {
- .entry = tch_wait_chunk_request_entry,
- .run = tch_wait_chunk_request_run,
- .exit = tch_wait_chunk_request_exit,
- },
- [TCH_MESSAGE_RECEIVED] = {
- .entry = tch_message_received_entry,
- .run = tch_message_received_run,
- },
- [TCH_MESSAGE_SENT] = {
- .entry = tch_message_sent_entry,
- },
- [TCH_REPORT_ERROR] = {
- .entry = tch_report_error_entry,
- },
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-};
-
-#ifdef TEST_BUILD
-
-const struct test_sm_data test_prl_sm_data[] = {
- {
- .base = prl_tx_states,
- .size = ARRAY_SIZE(prl_tx_states),
- .names = prl_tx_state_names,
- .names_size = ARRAY_SIZE(prl_tx_state_names),
- },
- {
- .base = prl_hr_states,
- .size = ARRAY_SIZE(prl_hr_states),
- .names = prl_hr_state_names,
- .names_size = ARRAY_SIZE(prl_hr_state_names),
- },
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
- {
- .base = rch_states,
- .size = ARRAY_SIZE(rch_states),
- .names = rch_state_names,
- .names_size = ARRAY_SIZE(rch_state_names),
- },
- {
- .base = tch_states,
- .size = ARRAY_SIZE(tch_states),
- .names = tch_state_names,
- .names_size = ARRAY_SIZE(tch_state_names),
- },
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-};
-BUILD_ASSERT(ARRAY_SIZE(prl_tx_states) == ARRAY_SIZE(prl_tx_state_names));
-BUILD_ASSERT(ARRAY_SIZE(prl_hr_states) == ARRAY_SIZE(prl_hr_state_names));
-#ifdef CONFIG_USB_PD_EXTENDED_MESSAGES
-BUILD_ASSERT(ARRAY_SIZE(rch_states) == ARRAY_SIZE(rch_state_names));
-BUILD_ASSERT(ARRAY_SIZE(tch_states) == ARRAY_SIZE(tch_state_names));
-#endif /* CONFIG_USB_PD_EXTENDED_MESSAGES */
-const int test_prl_sm_data_size = ARRAY_SIZE(test_prl_sm_data);
-#endif
diff --git a/common/usbc/usb_retimer_fw_update.c b/common/usbc/usb_retimer_fw_update.c
deleted file mode 100644
index 1ff198c78f..0000000000
--- a/common/usbc/usb_retimer_fw_update.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/* Copyright 2021 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.
- */
-
-#include <stdbool.h>
-#include <stdint.h>
-#include "compile_time_macros.h"
-#include "console.h"
-#include "hooks.h"
-#include "timer.h"
-#include "usb_common.h"
-#include "usb_mux.h"
-#include "usb_tc_sm.h"
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#else
-#define CPRINTS(format, args...)
-#define CPRINTF(format, args...)
-#endif
-
-/*
- * Retimer firmware update is initiated by AP.
- * The operations requested by AP are:
- * 0 - USB_RETIMER_FW_UPDATE_QUERY_PORT
- * 1 - USB_RETIMER_FW_UPDATE_SUSPEND_PD
- * 2 - USB_RETIMER_FW_UPDATE_RESUME_PD
- * 3 - USB_RETIMER_FW_UPDATE_GET_MUX
- * 4 - USB_RETIMER_FW_UPDATE_SET_USB
- * 5 - USB_RETIMER_FW_UPDATE_SET_SAFE
- * 6 - USB_RETIMER_FW_UPDATE_SET_TBT
- * 7 - USB_RETIMER_FW_UPDATE_DISCONNECT
- *
- * Operation 0 is processed immediately.
- * Operations 1 to 7 are deferred and processed inside tc_run().
- * Operations 1/2/3 can be processed any time; while 4/5/6/7 have
- * to be processed when PD task is suspended.
- * Two TC flags are created for this situation.
- * If Op 1/2/3 is received, TC_FLAGS_USB_RETIMER_FW_UPDATE_RUN
- * is set, PD task will be waken up and process it.
- * If 4/5/6/7 is received, TC_FLAGS_USB_RETIMER_FW_UPDATE_LTD_RUN is
- * set, PD task should be in suspended mode and process it.
- *
- */
-
-#define SUSPEND 1
-#define RESUME 0
-
-/* Track current port AP requested to update retimer firmware */
-static int cur_port;
-static int last_op; /* Operation received from AP via ACPI_WRITE */
-/* Operation result returned to ACPI_READ */
-static int last_result;
-
-int usb_retimer_fw_update_get_result(void)
-{
- int result = 0;
-
- switch (last_op) {
- case USB_RETIMER_FW_UPDATE_SUSPEND_PD:
- if (last_result == USB_RETIMER_FW_UPDATE_ERR) {
- result = last_result;
- break;
- }
- /* fall through */
- case USB_RETIMER_FW_UPDATE_RESUME_PD:
- result = pd_is_port_enabled(cur_port);
- break;
- case USB_RETIMER_FW_UPDATE_QUERY_PORT:
- result = usb_mux_retimer_fw_update_port_info();
- break;
- case USB_RETIMER_FW_UPDATE_GET_MUX:
- case USB_RETIMER_FW_UPDATE_SET_USB:
- case USB_RETIMER_FW_UPDATE_SET_SAFE:
- case USB_RETIMER_FW_UPDATE_SET_TBT:
- case USB_RETIMER_FW_UPDATE_DISCONNECT:
- result = last_result;
- break;
- default:
- break;
- }
-
- return result;
-}
-
-static void deferred_pd_suspend(void)
-{
- pd_set_suspend(cur_port, SUSPEND);
-}
-DECLARE_DEFERRED(deferred_pd_suspend);
-
-static inline mux_state_t retimer_fw_update_usb_mux_get(int port)
-{
- return usb_mux_get(port) & USB_RETIMER_FW_UPDATE_MUX_MASK;
-}
-
-void usb_retimer_fw_update_process_op_cb(int port)
-{
- switch (last_op) {
- case USB_RETIMER_FW_UPDATE_SUSPEND_PD:
- last_result = 0;
- /*
- * Do not perform retimer firmware update process
- * if battery is not present, or battery level is low.
- */
- if (!pd_firmware_upgrade_check_power_readiness(port)) {
- last_result = USB_RETIMER_FW_UPDATE_ERR;
- break;
- }
-
- /*
- * If the port has entered low power mode, the PD task
- * is paused and will not complete processing of
- * pd_set_suspend(). Move pd_set_suspend() into a deferred
- * call so that it runs from the HOOKS task and can generate
- * a wake event to the PD task and enter suspended mode.
- */
- hook_call_deferred(&deferred_pd_suspend_data, 0);
- break;
- case USB_RETIMER_FW_UPDATE_RESUME_PD:
- pd_set_suspend(port, RESUME);
- break;
- case USB_RETIMER_FW_UPDATE_GET_MUX:
- last_result = retimer_fw_update_usb_mux_get(port);
- 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);
- break;
- case USB_RETIMER_FW_UPDATE_SET_SAFE:
- usb_mux_set_safe_mode(port);
- last_result = retimer_fw_update_usb_mux_get(port);
- 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);
- 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);
- break;
- default:
- break;
- }
-}
-
-void usb_retimer_fw_update_process_op(int port, int op)
-{
- ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT);
-
- /*
- * TODO(b/179220036): check not overlapping requests;
- * not change cur_port if retimer scan is in progress
- */
- last_op = op;
-
- switch (op) {
- case USB_RETIMER_FW_UPDATE_QUERY_PORT:
- break;
- /* Operations can't be processed in ISR, defer to later */
- case USB_RETIMER_FW_UPDATE_GET_MUX:
- last_result = USB_RETIMER_FW_UPDATE_INVALID_MUX;
- tc_usb_firmware_fw_update_run(port);
- 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:
- case USB_RETIMER_FW_UPDATE_SET_SAFE:
- case USB_RETIMER_FW_UPDATE_SET_TBT:
- case USB_RETIMER_FW_UPDATE_DISCONNECT:
- if (pd_is_port_enabled(port)) {
- last_result = USB_RETIMER_FW_UPDATE_ERR;
- } else {
- last_result = USB_RETIMER_FW_UPDATE_INVALID_MUX;
- tc_usb_firmware_fw_update_limited_run(port);
- }
- break;
- default:
- break;
- }
-}
diff --git a/common/usbc/usb_sm.c b/common/usbc/usb_sm.c
deleted file mode 100644
index 04b7193c0f..0000000000
--- a/common/usbc/usb_sm.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/* Copyright 2019 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.
- */
-
-#include "common.h"
-#include "console.h"
-#include "stdbool.h"
-#include "task.h"
-#include "usb_pd.h"
-#include "usb_sm.h"
-#include "util.h"
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USB, format, ## args)
-#else /* CONFIG_COMMON_RUNTIME */
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif
-
-/* Private structure (to this file) used to track state machine context */
-struct internal_ctx {
- usb_state_ptr last_entered;
- uint32_t running : 1;
- uint32_t enter : 1;
- uint32_t exit : 1;
-};
-BUILD_ASSERT(sizeof(struct internal_ctx) ==
- member_size(struct sm_ctx, internal));
-
-/* Gets the first shared parent state between a and b (inclusive) */
-static usb_state_ptr shared_parent_state(usb_state_ptr a, usb_state_ptr b)
-{
- const usb_state_ptr orig_b = b;
-
- /* There are no common ancestors */
- if (b == NULL)
- return NULL;
-
- /* This assumes that both A and B are NULL terminated without cycles */
- while (a != NULL) {
- /* We found a match return */
- if (a == b)
- return a;
-
- /*
- * Otherwise, increment b down the list for comparison until we
- * run out, then increment a and start over on b for comparison
- */
- if (b->parent == NULL) {
- a = a->parent;
- b = orig_b;
- } else {
- b = b->parent;
- }
- }
-
- return NULL;
-}
-
-/*
- * Call all entry functions of parents before children. If set_state is called
- * during one of the entry functions, then do not call any remaining entry
- * functions.
- */
-static void call_entry_functions(const int port,
- struct internal_ctx *const internal,
- const usb_state_ptr stop,
- const usb_state_ptr current)
-{
- if (current == stop)
- return;
-
- call_entry_functions(port, internal, stop, current->parent);
-
- /*
- * If the previous entry function called set_state, then don't enter
- * remaining states.
- */
- if (!internal->enter)
- return;
-
- /* Track the latest state that was entered, so we can exit properly. */
- internal->last_entered = current;
- if (current->entry)
- current->entry(port);
-}
-
-/*
- * Call all exit functions of children before parents. Note set_state is ignored
- * during an exit function.
- */
-static void call_exit_functions(const int port, const usb_state_ptr stop,
- const usb_state_ptr current)
-{
- if (current == stop)
- return;
-
- if (current->exit)
- current->exit(port);
-
- call_exit_functions(port, stop, current->parent);
-}
-
-void set_state(const int port, struct sm_ctx *const ctx,
- const usb_state_ptr new_state)
-{
- struct internal_ctx * const internal = (void *) ctx->internal;
- usb_state_ptr last_state;
- usb_state_ptr shared_parent;
-
- /*
- * It does not make sense to call set_state in an exit phase of a state
- * since we are already in a transition; we would always ignore the
- * intended state to transition into.
- */
- if (internal->exit) {
- CPRINTF("C%d: Ignoring set state to 0x%pP within 0x%pP",
- port, new_state, ctx->current);
- return;
- }
-
- /*
- * Determine the last state that was entered. Normally it is current,
- * but we could have called set_state within an entry phase, so we
- * shouldn't exit any states that weren't fully entered.
- */
- last_state = internal->enter ? internal->last_entered : ctx->current;
-
- /* We don't exit and re-enter shared parent states */
- shared_parent = shared_parent_state(last_state, new_state);
-
- /*
- * Exit all of the non-common states from the last state.
- */
- internal->exit = true;
- call_exit_functions(port, shared_parent, last_state);
- internal->exit = false;
-
- ctx->previous = ctx->current;
- ctx->current = new_state;
-
- /*
- * Enter all new non-common states. last_entered will contain the last
- * state that successfully entered before another set_state was called.
- */
- internal->last_entered = NULL;
- internal->enter = true;
- call_entry_functions(port, internal, shared_parent, ctx->current);
- /*
- * Setting enter to false ensures that all pending entry calls will be
- * skipped (in the case of a parent state calling set_state, which means
- * we should not enter any child states)
- */
- internal->enter = false;
-
- /*
- * If we set_state while we are running a child state, then stop running
- * any remaining parent states.
- */
- internal->running = false;
-
- /*
- * Since we are changing states, we want to ensure that we process the
- * next state's run method as soon as we can to ensure that we don't
- * delay important processing until the next task interval.
- */
- if (IS_ENABLED(HAS_TASK_PD_C0))
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-/*
- * Call all run functions of children before parents. If set_state is called
- * during one of the entry functions, then do not call any remaining entry
- * functions.
- */
-static void call_run_functions(const int port,
- const struct internal_ctx *const internal,
- const usb_state_ptr current)
-{
- if (!current)
- return;
-
- /* If set_state is called during run, don't call remain functions. */
- if (!internal->running)
- return;
-
- if (current->run)
- current->run(port);
-
- call_run_functions(port, internal, current->parent);
-}
-
-void run_state(const int port, struct sm_ctx *const ctx)
-{
- struct internal_ctx * const internal = (void *) ctx->internal;
-
- internal->running = true;
- call_run_functions(port, internal, ctx->current);
- internal->running = false;
-}
diff --git a/common/usbc/usb_tc_ctvpd_sm.c b/common/usbc/usb_tc_ctvpd_sm.c
deleted file mode 100644
index a2babe754a..0000000000
--- a/common/usbc/usb_tc_ctvpd_sm.c
+++ /dev/null
@@ -1,1716 +0,0 @@
-/* Copyright 2019 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.
- */
-
-#include "common.h"
-#include "console.h"
-#include "system.h"
-#include "task.h"
-#include "tcpm/tcpm.h"
-#include "usb_pd.h"
-#include "usb_tc_sm.h"
-#include "vpd_api.h"
-
-/* USB Type-C CTVPD module */
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#else /* CONFIG_COMMON_RUNTIME */
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif
-
-/* Type-C Layer Flags */
-#define TC_FLAGS_VCONN_ON BIT(0)
-
-#define SUPPORT_TIMER_RESET_INIT 0
-#define SUPPORT_TIMER_RESET_REQUEST 1
-#define SUPPORT_TIMER_RESET_COMPLETE 2
-
-/**
- * This is the Type-C Port object that contains information needed to
- * implement a Charge Through VCONN Powered Device.
- */
-static struct type_c {
- /* state machine context */
- struct sm_ctx ctx;
- /* Higher-level power deliver state machines are enabled if true. */
- uint8_t pd_enable;
- /* port flags, see TC_FLAGS_* */
- uint32_t flags;
- /*
- * Time a charge-through port shall wait before it can determine it
- * is attached
- */
- uint64_t cc_debounce;
- /* Time a host port shall wait before it can determine it is attached */
- uint64_t host_cc_debounce;
- /* Time a Sink port shall wait before it can determine it is detached
- * due to the potential for USB PD signaling on CC as described in
- * the state definitions.
- */
- uint64_t pd_debounce;
- /* Maintains state of billboard device */
- int billboard_presented;
- /*
- * Time a port shall wait before it can determine it is
- * re-attached during the try-wait process.
- */
- uint64_t try_wait_debounce;
- /* charge-through support timer */
- uint64_t support_timer;
- /* reset the charge-through support timer */
- uint8_t support_timer_reset;
- /* VPD host port cc state */
- enum pd_cc_states host_cc_state;
- uint8_t ct_cc;
- /* The cc state */
- enum pd_cc_states cc_state;
- uint64_t next_role_swap;
-} tc[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* List of all TypeC-level states */
-enum usb_tc_state {
- /* Normal States */
- TC_DISABLED,
- TC_UNATTACHED_SNK,
- TC_ATTACH_WAIT_SNK,
- TC_ATTACHED_SNK,
- TC_ERROR_RECOVERY,
- TC_TRY_SNK,
- TC_UNATTACHED_SRC,
- TC_ATTACH_WAIT_SRC,
- TC_TRY_WAIT_SRC,
- TC_ATTACHED_SRC,
- TC_CT_TRY_SNK,
- TC_CT_ATTACH_WAIT_UNSUPPORTED,
- TC_CT_ATTACHED_UNSUPPORTED,
- TC_CT_UNATTACHED_UNSUPPORTED,
- TC_CT_UNATTACHED_VPD,
- TC_CT_DISABLED_VPD,
- TC_CT_ATTACHED_VPD,
- TC_CT_ATTACH_WAIT_VPD,
- /* Super States */
- TC_VBUS_CC_ISO,
- TC_HOST_RARD_CT_RD,
- TC_HOST_OPEN_CT_OPEN,
- TC_HOST_RP3_CT_RD,
- TC_HOST_RP3_CT_RPU,
- TC_HOST_RPU_CT_RD,
-};
-
-/* Forward declare the full list of states. This is indexed by usb_tc_state */
-static const struct usb_state tc_states[];
-
-
-/* List of human readable state names for console debugging */
-__maybe_unused const char * const tc_state_names[] = {
-#ifdef CONFIG_COMMON_RUNTIME
- [TC_DISABLED] = "Disabled",
- [TC_UNATTACHED_SNK] = "Unattached.SNK",
- [TC_ATTACH_WAIT_SNK] = "AttachWait.SNK",
- [TC_ATTACHED_SNK] = "Attached.SNK",
- [TC_ERROR_RECOVERY] = "ErrorRecovery",
- [TC_TRY_SNK] = "Try.SNK",
- [TC_UNATTACHED_SRC] = "Unattached.SRC",
- [TC_ATTACH_WAIT_SRC] = "AttachWait.SRC",
- [TC_TRY_WAIT_SRC] = "TryWait.SRC",
- [TC_ATTACHED_SRC] = "Attached.SRC",
- [TC_CT_TRY_SNK] = "CTTry.SNK",
- [TC_CT_ATTACH_WAIT_UNSUPPORTED] = "CTAttachWait.Unsupported",
- [TC_CT_ATTACHED_UNSUPPORTED] = "CTAttached.Unsupported",
- [TC_CT_UNATTACHED_UNSUPPORTED] = "CTUnattached.Unsupported",
- [TC_CT_UNATTACHED_VPD] = "CTUnattached.VPD",
- [TC_CT_DISABLED_VPD] = "CTDisabled.VPD",
- [TC_CT_ATTACHED_VPD] = "CTAttached.VPD",
- [TC_CT_ATTACH_WAIT_VPD] = "CTAttachWait.VPD",
-#endif
-};
-
-/* Forward declare private, common functions */
-static void set_state_tc(const int port, enum usb_tc_state new_state);
-
-/* Public TypeC functions */
-
-enum pd_power_role pd_get_power_role(int port)
-{
- /* Vconn power device is always the sink */
- return PD_ROLE_SINK;
-}
-
-enum pd_cable_plug tc_get_cable_plug(int port)
-{
- /* Vconn power device is always the cable */
- return PD_PLUG_FROM_CABLE;
-}
-
-enum pd_data_role pd_get_data_role(int port)
-{
- /* Vconn power device doesn't have a data role, but UFP matches SNK */
- return PD_ROLE_UFP;
-}
-
-/* Note tc_set_power_role and tc_set_data_role are unimplemented */
-
-uint8_t tc_get_polarity(int port)
-{
- /* Does not track polarity */
- return 0;
-}
-
-uint8_t tc_get_pd_enabled(int port)
-{
- return tc[port].pd_enable;
-}
-
-void tc_reset_support_timer(int port)
-{
- tc[port].support_timer_reset |= SUPPORT_TIMER_RESET_REQUEST;
-}
-
-/*
- * TCPC CC/Rp management
- *
- * Stub for linking purposes.
- * This is not supported for ctvpd, we are never the SOP partner.
- */
-void typec_select_pull(int port, enum tcpc_cc_pull pull)
-{
-}
-void typec_select_src_current_limit_rp(int port, enum tcpc_rp_value rp)
-{
-}
-void typec_select_src_collision_rp(int port, enum tcpc_rp_value rp)
-{
-}
-int typec_update_cc(int port)
-{
- return EC_SUCCESS;
-}
-
-void tc_state_init(int port)
-{
- int res = 0;
-
- res = tcpm_init(port);
-
- CPRINTS("C%d: init %s", port, res ? "failed" : "ready");
-
- /* Disable if restart failed, otherwise start in default state. */
- set_state_tc(port, res ? TC_DISABLED : TC_UNATTACHED_SNK);
-
- /* Disable pd state machines */
- tc[port].pd_enable = 0;
- tc[port].billboard_presented = 0;
- tc[port].flags = 0;
-}
-
-void tc_event_check(int port, int evt)
-{
- /* Do Nothing */
-}
-
-void tc_run(const int port)
-{
- run_state(port, &tc[port].ctx);
-}
-
-/* Internal Functions */
-
-/* Set the TypeC state machine to a new state. */
-static void set_state_tc(const int port, enum usb_tc_state new_state)
-{
- set_state(port, &tc[port].ctx, &tc_states[new_state]);
-}
-
-/* Get the current TypeC state. */
-test_export_static enum usb_tc_state get_state_tc(const int port)
-{
- return tc[port].ctx.current - &tc_states[0];
-}
-
-/* Get the previous TypeC state. */
-static enum usb_tc_state get_last_state_tc(const int port)
-{
- return tc[port].ctx.previous - &tc_states[0];
-}
-
-test_mockable_static void print_current_state(const int port)
-{
- CPRINTS("C%d: %s", port, tc_state_names[get_state_tc(port)]);
-}
-
-int pd_is_connected(int port)
-{
- return (get_state_tc(port) == TC_ATTACHED_SNK) ||
- (get_state_tc(port) == TC_ATTACHED_SRC) ||
- (get_state_tc(port) == TC_CT_ATTACHED_UNSUPPORTED) ||
- (get_state_tc(port) == TC_CT_ATTACHED_VPD);
-}
-
-bool pd_is_disconnected(int port)
-{
- return !pd_is_connected(port);
-}
-
-/**
- * Disabled
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Remove the terminations from Host
- * Remove the terminations from Charge-Through
- */
-static void tc_disabled_entry(const int port)
-{
- print_current_state(port);
-}
-
-static void tc_disabled_run(const int port)
-{
- task_wait_event(-1);
-}
-
-static void tc_disabled_exit(const int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_TCPC)) {
- if (tcpm_init(port) != 0) {
- CPRINTS("C%d: restart failed!", port);
- return;
- }
- }
-
- CPRINTS("C%d: resumed!", port);
-}
-
-void pd_set_suspend(int port, int suspend)
-{
- /*
- * This shouldn't happen. If it does, we need to send an event to the
- * PD task to put the SM into the disabled state. It is not safe to
- * directly set_state here since this may be in another task.
- */
- assert(false);
-}
-
-/**
- * ErrorRecovery
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Remove the terminations from Host
- * Remove the terminations from Charge-Through
- */
-static void tc_error_recovery_entry(const int port)
-{
- print_current_state(port);
- /* Use cc_debounce state variable for error recovery timeout */
- tc[port].cc_debounce = get_time().val + PD_T_ERROR_RECOVERY;
-}
-
-static void tc_error_recovery_run(const int port)
-{
- if (get_time().val > tc[port].cc_debounce)
- set_state_tc(port, TC_UNATTACHED_SNK);
-}
-
-/**
- * Unattached.SNK
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place Ra on VCONN and Rd on Host CC
- * Place Rd on Charge-Through CCs
- */
-static void tc_unattached_snk_entry(const int port)
-{
- if (get_last_state_tc(port) != TC_UNATTACHED_SRC)
- print_current_state(port);
-
- tc[port].flags &= ~TC_FLAGS_VCONN_ON;
- tc[port].cc_state = PD_CC_UNSET;
-}
-
-static void tc_unattached_snk_run(const int port)
-{
- int host_cc;
- int new_cc_state;
- int cc1;
- int cc2;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- /*
- * Transition to AttachWait.SNK when a Source connection is
- * detected, as indicated by the SNK.Rp state on its Host-side
- * port’s CC pin.
- */
- if (cc_is_rp(host_cc)) {
- set_state_tc(port, TC_ATTACH_WAIT_SNK);
- return;
- }
-
- /* Check Charge-Through CCs for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (cc_is_rp(cc1) != cc_is_rp(cc2))
- new_cc_state = PD_CC_DFP_ATTACHED;
- else
- new_cc_state = PD_CC_NONE;
-
- /* Debounce Charge-Through CC state */
- if (tc[port].cc_state != new_cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE;
- }
-
- /* If we are here, Host CC must be open */
-
- /* Wait for Charge-Through CC debounce */
- if (get_time().val < tc[port].cc_debounce)
- return;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Unattached.SRC when the state of the Host-side port’s CC pin is
- * SNK.Open for tDRP − dcSRC.DRP ∙ tDRP and both of the following
- * is detected on the Charge-Through port.
- * 1) SNK.Rp state is detected on exactly one of the CC1 or CC2
- * pins for at least tCCDebounce
- * 2) VBUS is detected
- */
- if (vpd_is_ct_vbus_present() &&
- tc[port].cc_state == PD_CC_DFP_ATTACHED) {
- set_state_tc(port, TC_UNATTACHED_SRC);
- return;
- }
-}
-
-/**
- * AttachWait.SNK
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place Ra on VCONN and Rd on Host CC
- * Place Rd on Charge-Through CCs
- */
-static void tc_attach_wait_snk_entry(const int port)
-{
- print_current_state(port);
- tc[port].host_cc_state = PD_CC_UNSET;
-}
-
-static void tc_attach_wait_snk_run(const int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (cc_is_rp(host_cc))
- host_new_cc_state = PD_CC_DFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- if (host_new_cc_state == PD_CC_DFP_ATTACHED)
- tc[port].host_cc_debounce = get_time().val +
- PD_T_CC_DEBOUNCE;
- else
- tc[port].host_cc_debounce = get_time().val +
- PD_T_PD_DEBOUNCE;
- return;
- }
-
- /* Wait for Host CC debounce */
- if (get_time().val < tc[port].host_cc_debounce)
- return;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Attached.SNK after the state of the Host-side port’s CC pin is
- * SNK.Rp for at least tCCDebounce and either host-side VCONN or
- * VBUS is detected.
- *
- * Transition to Unattached.SNK when the state of both the CC1 and
- * CC2 pins is SNK.Open for at least tPDDebounce.
- */
- if (tc[port].host_cc_state == PD_CC_DFP_ATTACHED &&
- (vpd_is_vconn_present() || vpd_is_host_vbus_present()))
- set_state_tc(port, TC_ATTACHED_SNK);
- else if (tc[port].host_cc_state == PD_CC_NONE)
- set_state_tc(port, TC_UNATTACHED_SNK);
-}
-
-/**
- * Attached.SNK
- */
-static void tc_attached_snk_entry(const int port)
-{
- print_current_state(port);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- pd_set_polarity(port, 0);
-
- /*
- * This state can only be entered from states AttachWait.SNK
- * and Try.SNK. So the Host port is isolated from the
- * Charge-Through port. We only need to High-Z the
- * Charge-Through ports CC1 and CC2 pins.
- */
- vpd_ct_set_pull(TYPEC_CC_OPEN, 0);
-
- tc[port].host_cc_state = PD_CC_UNSET;
-
- /* Start Charge-Through support timer */
- tc[port].support_timer_reset = SUPPORT_TIMER_RESET_INIT;
- tc[port].support_timer = get_time().val + PD_T_AME;
-}
-
-static void tc_attached_snk_run(const int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /* Has host vbus and vconn been removed */
- if (!vpd_is_host_vbus_present() && !vpd_is_vconn_present()) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /*
- * Reset the Charge-Through Support Timer when it first
- * receives any USB PD Structured VDM Command it supports,
- * which is the Discover Identity command. And this is only
- * done one time.
- */
- if (tc[port].support_timer_reset == SUPPORT_TIMER_RESET_REQUEST) {
- tc[port].support_timer_reset |= SUPPORT_TIMER_RESET_COMPLETE;
- tc[port].support_timer = get_time().val + PD_T_AME;
- }
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (cc_is_rp(host_cc))
- host_new_cc_state = PD_CC_DFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- tc[port].host_cc_debounce = get_time().val + PD_T_VPDCTDD;
- return;
- }
-
- /* Wait for Host CC debounce */
- if (get_time().val < tc[port].host_cc_debounce)
- return;
-
- if (vpd_is_vconn_present()) {
- if (!(tc[port].flags & TC_FLAGS_VCONN_ON)) {
- /* VCONN detected. Remove RA */
- vpd_host_set_pull(TYPEC_CC_RD, 0);
- tc[port].flags |= TC_FLAGS_VCONN_ON;
- }
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to CTUnattached.VPD if VCONN is present and the state of
- * its Host-side port’s CC pin is SNK.Open for tVPDCTDD.
- */
- if (tc[port].host_cc_state == PD_CC_NONE) {
- set_state_tc(port, TC_CT_UNATTACHED_VPD);
- return;
- }
- }
-
- /* Check the Support Timer */
- if (get_time().val > tc[port].support_timer &&
- !tc[port].billboard_presented) {
- /*
- * Present USB Billboard Device Class interface
- * indicating that Charge-Through is not supported
- */
- tc[port].billboard_presented = 1;
- vpd_present_billboard(BB_SNK);
- }
-}
-
-static void tc_attached_snk_exit(const int port)
-{
- tc[port].billboard_presented = 0;
- vpd_present_billboard(BB_NONE);
-}
-
-/**
- * Super State HOST_RA_CT_RD
- */
-static void tc_host_rard_ct_rd_entry(const int port)
-{
- /* Place Ra on VCONN and Rd on Host CC */
- vpd_host_set_pull(TYPEC_CC_RA_RD, 0);
-
- /* Place Rd on Charge-Through CCs */
- vpd_ct_set_pull(TYPEC_CC_RD, 0);
-}
-
-/**
- * Super State HOST_OPEN_CT_OPEN
- */
-static void tc_host_open_ct_open_entry(const int port)
-{
- /* Remove the terminations from Host */
- vpd_host_set_pull(TYPEC_CC_OPEN, 0);
-
- /* Remove the terminations from Charge-Through */
- vpd_ct_set_pull(TYPEC_CC_OPEN, 0);
-}
-
-/**
- * Super State VBUS_CC_ISO
- */
-static void tc_vbus_cc_iso_entry(const int port)
-{
- /* Isolate the Host-side port from the Charge-Through port */
- vpd_vbus_pass_en(0);
-
- /* Remove Charge-Through side port CCs */
- vpd_ct_cc_sel(CT_OPEN);
-
- /* Enable mcu communication and cc */
- vpd_mcu_cc_en(1);
-}
-
-/**
- * Unattached.SRC
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RpUSB on Host CC
- * Place Rd on Charge-Through CCs
- */
-static void tc_unattached_src_entry(const int port)
-{
- if (get_last_state_tc(port) != TC_UNATTACHED_SNK)
- print_current_state(port);
-
- /* Get power from VBUS */
- vpd_vconn_pwr_sel_odl(PWR_VBUS);
-
- /* Make sure it's the Charge-Through Port's VBUS */
- if (!vpd_is_ct_vbus_present()) {
- set_state_tc(port, TC_ERROR_RECOVERY);
- return;
- }
-
- tc[port].next_role_swap = get_time().val + PD_T_DRP_SRC;
-}
-
-static void tc_unattached_src_run(const int port)
-{
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- /*
- * Transition to AttachWait.SRC when host-side VBUS is
- * vSafe0V and SRC.Rd state is detected on the Host-side
- * port’s CC pin.
- */
- if (!vpd_is_host_vbus_present() && host_cc == TYPEC_CC_VOLT_RD) {
- set_state_tc(port, TC_ATTACH_WAIT_SRC);
- return;
- }
-
- /*
- * Transition to Unattached.SNK within tDRPTransition or
- * if Charge-Through VBUS is removed.
- */
- if (!vpd_is_ct_vbus_present() ||
- get_time().val > tc[port].next_role_swap) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-}
-
-/**
- * AttachWait.SRC
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RpUSB on Host CC
- * Place Rd on Charge-Through CCs
- */
-static void tc_attach_wait_src_entry(const int port)
-{
- print_current_state(port);
-
- tc[port].host_cc_state = PD_CC_UNSET;
-}
-
-static void tc_attach_wait_src_run(const int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (host_cc == TYPEC_CC_VOLT_RD)
- host_new_cc_state = PD_CC_UFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to Unattached.SNK when the SRC.Open state is detected on the
- * Host-side port’s CC or if Charge-Through VBUS falls below
- * vSinkDisconnect. The Charge-Through VCONN-Powered USB Device
- * shall detect the SRC.Open state within tSRCDisconnect, but
- * should detect it as quickly as possible.
- */
- if (host_new_cc_state == PD_CC_NONE || !vpd_is_ct_vbus_present()) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE;
- return;
- }
-
- /* Wait for Host CC debounce */
- if (get_time().val < tc[port].cc_debounce)
- return;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Try.SNK when the host-side VBUS is at vSafe0V and the SRC.Rd
- * state is on the Host-side port’s CC pin for at least tCCDebounce.
- */
- if (tc[port].host_cc_state == PD_CC_UFP_ATTACHED &&
- !vpd_is_host_vbus_present()) {
- set_state_tc(port, TC_TRY_SNK);
- return;
- }
-}
-
-/**
- * Attached.SRC
- */
-static void tc_attached_src_entry(const int port)
-{
- print_current_state(port);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- pd_set_polarity(port, 0);
-
- /* Connect Charge-Through VBUS to Host VBUS */
- vpd_vbus_pass_en(1);
-
- /*
- * Get power from VBUS. No need to test because
- * the Host VBUS is connected to the Charge-Through
- * VBUS
- */
- vpd_vconn_pwr_sel_odl(PWR_VBUS);
-}
-
-static void tc_attached_src_run(const int port)
-{
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Unattached.SNK when VBUS falls below vSinkDisconnect or the
- * Host-side port’s CC pin is SRC.Open. The Charge-Through
- * VCONNPowered USB Device shall detect the SRC.Open state within
- * tSRCDisconnect, but should detect it as quickly as possible.
- */
- if (!vpd_is_ct_vbus_present() || host_cc == TYPEC_CC_VOLT_OPEN)
- set_state_tc(port, TC_UNATTACHED_SNK);
-}
-
-/**
- * Super State HOST_RPU_CT_RD
- */
-static void tc_host_rpu_ct_rd_entry(const int port)
-{
- /* Place RpUSB on Host CC */
- vpd_host_set_pull(TYPEC_CC_RP, TYPEC_RP_USB);
-
- /* Place Rd on Charge-Through CCs */
- vpd_ct_set_pull(TYPEC_CC_RD, 0);
-}
-
-/**
- * Try.SNK
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place Ra on VCONN and Rd on Host CC
- * Place Rd on Charge-Through CCs
- */
-static void tc_try_snk_entry(const int port)
-{
- print_current_state(port);
-
- /* Get power from VBUS */
- vpd_vconn_pwr_sel_odl(PWR_VBUS);
-
- /* Make sure it's the Charge-Through Port's VBUS */
- if (!vpd_is_ct_vbus_present()) {
- set_state_tc(port, TC_ERROR_RECOVERY);
- return;
- }
-
- tc[port].host_cc_state = PD_CC_UNSET;
-
- /* Using next_role_swap timer as try_src timer */
- tc[port].next_role_swap = get_time().val + PD_T_DRP_TRY;
-}
-
-static void tc_try_snk_run(const int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /*
- * Wait for tDRPTry before monitoring the Charge-Through
- * port’s CC pins for the SNK.Rp
- */
- if (get_time().val < tc[port].next_role_swap)
- return;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (cc_is_rp(host_cc))
- host_new_cc_state = PD_CC_DFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_DEBOUNCE;
- return;
- }
-
- /* Wait for Host CC debounce */
- if (get_time().val < tc[port].cc_debounce)
- return;
-
- /*
- * The Charge-Through VCONN-Powered USB Device shall then transition to
- * Attached.SNK when the SNK.Rp state is detected on the Host-side
- * port’s CC pin for at least tTryCCDebounce and VBUS or VCONN is
- * detected on Host-side port.
- *
- * Alternatively, the Charge-Through VCONN-Powered USB Device shall
- * transition to TryWait.SRC if Host-side SNK.Rp state is not detected
- * for tTryCCDebounce.
- */
- if (tc[port].host_cc_state == PD_CC_DFP_ATTACHED &&
- (vpd_is_host_vbus_present() || vpd_is_vconn_present()))
- set_state_tc(port, TC_ATTACHED_SNK);
- else if (tc[port].host_cc_state == PD_CC_NONE)
- set_state_tc(port, TC_TRY_WAIT_SRC);
-}
-
-/**
- * TryWait.SRC
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RpUSB on Host CC
- * Place Rd on Charge-Through CCs
- */
-static void tc_try_wait_src_entry(const int port)
-{
- print_current_state(port);
-
- tc[port].host_cc_state = PD_CC_UNSET;
- tc[port].next_role_swap = get_time().val + PD_T_DRP_TRY;
-}
-
-static void tc_try_wait_src_run(const int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (host_cc == TYPEC_CC_VOLT_RD)
- host_new_cc_state = PD_CC_UFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- tc[port].host_cc_debounce =
- get_time().val + PD_T_TRY_CC_DEBOUNCE;
- return;
- }
-
- if (get_time().val > tc[port].host_cc_debounce) {
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to Attached.SRC when host-side VBUS is at vSafe0V and the
- * SRC.Rd state is detected on the Host-side port’s CC pin for
- * at least tTryCCDebounce.
- */
- if (tc[port].host_cc_state == PD_CC_UFP_ATTACHED &&
- !vpd_is_host_vbus_present()) {
- set_state_tc(port, TC_ATTACHED_SRC);
- return;
- }
- }
-
- if (get_time().val > tc[port].next_role_swap) {
- /*
- * The Charge-Through VCONN-Powered USB Device shall transition
- * to Unattached.SNK after tDRPTry if the Host-side port’s CC
- * pin is not in the SRC.Rd state.
- */
- if (tc[port].host_cc_state == PD_CC_NONE) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
- }
-}
-
-/**
- * CTTry.SNK
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Connect Charge-Through Rd
- * Get power from VCONN
- */
-static void tc_ct_try_snk_entry(const int port)
-{
- print_current_state(port);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- pd_set_polarity(port, 0);
-
- tc[port].cc_state = PD_CC_UNSET;
- tc[port].next_role_swap = get_time().val + PD_T_DRP_TRY;
-}
-
-static void tc_ct_try_snk_run(const int port)
-{
- int new_cc_state;
- int cc1;
- int cc2;
-
- /*
- * Wait for tDRPTry before monitoring the Charge-Through
- * port’s CC pins for the SNK.Rp
- */
- if (get_time().val < tc[port].next_role_swap)
- return;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (cc_is_rp(cc1) || cc_is_rp(cc2))
- new_cc_state = PD_CC_DFP_ATTACHED;
- else
- new_cc_state = PD_CC_NONE;
-
- /*
- * The Charge-Through VCONN-Powered USB Device shall transition
- * to Unattached.SNK if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /* Debounce the CT CC state */
- if (tc[port].cc_state != new_cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_DEBOUNCE;
- tc[port].try_wait_debounce = get_time().val + PD_T_TRY_WAIT;
-
- return;
- }
-
- if (get_time().val > tc[port].cc_debounce) {
- /*
- * The Charge-Through VCONN-Powered USB Device shall then
- * transition to CTAttached.VPD when the SNK.Rp state is
- * detected on the Charge-Through port’s CC pins for at
- * least tTryCCDebounce and VBUS is detected on
- * Charge-Through port.
- */
- if (tc[port].cc_state == PD_CC_DFP_ATTACHED &&
- vpd_is_ct_vbus_present()) {
- set_state_tc(port, TC_CT_ATTACHED_VPD);
- return;
- }
- }
-
- if (get_time().val > tc[port].try_wait_debounce) {
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to CTAttached.Unsupported if SNK.Rp state is not detected
- * for tDRPTryWait.
- */
- if (tc[port].cc_state == PD_CC_NONE) {
- set_state_tc(port,
- TC_CT_ATTACHED_UNSUPPORTED);
- return;
- }
- }
-}
-
-static void tc_ct_try_snk_exit(const int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
-}
-
-/**
- * CTAttachWait.Unsupported
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Place RPUSB on Charge-Through CC
- * Get power from VCONN
- */
-static void tc_ct_attach_wait_unsupported_entry(const int port)
-{
- print_current_state(port);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- pd_set_polarity(port, 0);
-
- tc[port].cc_state = PD_CC_UNSET;
-}
-
-static void tc_ct_attach_wait_unsupported_run(const int port)
-{
- int new_cc_state;
- int cc1;
- int cc2;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (cc_is_at_least_one_rd(cc1, cc2))
- new_cc_state = PD_CC_UFP_ATTACHED;
- else if (cc_is_audio_acc(cc1, cc2))
- new_cc_state = PD_CC_UFP_AUDIO_ACC;
- else /* (cc1 == TYPEC_CC_VOLT_OPEN or cc2 == TYPEC_CC_VOLT_OPEN */
- new_cc_state = PD_CC_NONE;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Unattached.SNK if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /* Debounce the cc state */
- if (tc[port].cc_state != new_cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_CC_DEBOUNCE;
- return;
- }
-
- /* Wait for CC debounce */
- if (get_time().val < tc[port].cc_debounce)
- return;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTUnattached.VPD when the state of either the Charge-Through
- * Port’s CC1 or CC2 pin is SRC.Open for at least tCCDebounce.
- *
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTTry.SNK if the state of at least one of the Charge-Through
- * port’s CC pins is SRC.Rd, or if the state of both the CC1 and CC2
- * pins is SRC.Ra. for at least tCCDebounce.
- */
- if (new_cc_state == PD_CC_NONE)
- set_state_tc(port, TC_CT_UNATTACHED_VPD);
- else /* PD_CC_UFP_ATTACHED or PD_CC_UFP_AUDIO_ACC */
- set_state_tc(port, TC_CT_TRY_SNK);
-}
-
-static void tc_ct_attach_wait_unsupported_exit(const int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
-}
-
-/**
- * CTAttached.Unsupported
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Place RPUSB on Charge-Through CC
- * Get power from VCONN
- */
-static void tc_ct_attached_unsupported_entry(const int port)
-{
- print_current_state(port);
-
- /* Present Billboard device */
- vpd_present_billboard(BB_SNK);
-}
-
-static void tc_ct_attached_unsupported_run(const int port)
-{
- int cc1;
- int cc2;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (!vpd_is_vconn_present()) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /*
- * The Charge-Through VCONN-Powered USB Device shall transition to
- * CTUnattached.VPD when SRC.Open state is detected on both the
- * Charge-Through port’s CC pins or the SRC.Open state is detected
- * on one CC pin and SRC.Ra is detected on the other CC pin.
- */
- if ((cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_OPEN) ||
- (cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_RA) ||
- (cc1 == TYPEC_CC_VOLT_RA && cc2 == TYPEC_CC_VOLT_OPEN)) {
- set_state_tc(port, TC_CT_UNATTACHED_VPD);
- return;
- }
-}
-
-static void tc_ct_attached_unsupported_exit(const int port)
-{
- vpd_present_billboard(BB_NONE);
-}
-
-/**
- * CTUnattached.Unsupported
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Place RPUSB on Charge-Through CC
- * Get power from VCONN
- */
-static void tc_ct_unattached_unsupported_entry(const int port)
-{
- if (get_last_state_tc(port) != TC_CT_UNATTACHED_VPD)
- print_current_state(port);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- pd_set_polarity(port, 0);
-
- tc[port].next_role_swap = get_time().val + PD_T_DRP_SRC;
-}
-
-static void tc_ct_unattached_unsupported_run(const int port)
-{
- int cc1;
- int cc2;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTAttachWait.Unsupported when a Sink connection is detected on
- * the Charge-Through port, as indicated by the SRC.Rd state on at
- * least one of the Charge-Through port’s CC pins or SRC.Ra state
- * on both the CC1 and CC2 pins.
- */
- if (cc_is_at_least_one_rd(cc1, cc2) || cc_is_audio_acc(cc1, cc2)) {
- set_state_tc(port,
- TC_CT_ATTACH_WAIT_UNSUPPORTED);
- return;
- }
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Unattached.SNK if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTUnattached.VPD within tDRPTransition after dcSRC.DRP ∙ tDRP.
- */
- if (get_time().val > tc[port].next_role_swap) {
- set_state_tc(port, TC_CT_UNATTACHED_VPD);
- return;
- }
-}
-
-static void tc_ct_unattached_unsupported_exit(const int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
-}
-
-/**
- * CTUnattached.VPD
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Connect Charge-Through Rd
- * Get power from VCONN
- */
-static void tc_ct_unattached_vpd_entry(const int port)
-{
- if (get_last_state_tc(port) != TC_CT_UNATTACHED_UNSUPPORTED)
- print_current_state(port);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- pd_set_polarity(port, 0);
-
- tc[port].cc_state = PD_CC_UNSET;
-}
-
-static void tc_ct_unattached_vpd_run(const int port)
-{
- int new_cc_state;
- int cc1;
- int cc2;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (cc_is_rp(cc1) != cc_is_rp(cc2))
- new_cc_state = PD_CC_DFP_ATTACHED;
- else if (!cc_is_rp(cc1) && !cc_is_rp(cc2))
- new_cc_state = PD_CC_NONE;
- else
- new_cc_state = PD_CC_UNSET;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTAttachWait.VPD when a Source connection is detected on the
- * Charge-Through port, as indicated by the SNK.Rp state on
- * exactly one of the Charge-Through port’s CC pins.
- */
- if (new_cc_state == PD_CC_DFP_ATTACHED) {
- set_state_tc(port, TC_CT_ATTACH_WAIT_VPD);
- return;
- }
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * Unattached.SNK if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_DRP_SRC;
- return;
- }
-
- if (get_time().val < tc[port].cc_debounce)
- return;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTUnattached.Unsupported within tDRPTransition after the state
- * of both the Charge-Through port’s CC1 and CC2 pins is SNK.Open
- * for tDRP-dcSRC.DRP ∙ tDRP, or if directed.
- */
- if (tc[port].cc_state == PD_CC_NONE) {
- set_state_tc(port, TC_CT_UNATTACHED_UNSUPPORTED);
- return;
- }
-}
-
-static void tc_ct_unattached_vpd_exit(const int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
-}
-
-/**
- * CTDisabled.VPD
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Remove the terminations from Host
- * Remove the terminations from Charge-Through
- */
-static void tc_ct_disabled_vpd_entry(const int port)
-{
- print_current_state(port);
-
- /* Get power from VBUS */
- vpd_vconn_pwr_sel_odl(PWR_VBUS);
-
- tc[port].next_role_swap = get_time().val + PD_T_VPDDISABLE;
-}
-
-static void tc_ct_disabled_vpd_run(const int port)
-{
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to Unattached.SNK after tVPDDisable.
- */
- if (get_time().val > tc[port].next_role_swap)
- set_state_tc(port, TC_UNATTACHED_SNK);
-}
-
-/**
- * CTAttached.VPD
- */
-static void tc_ct_attached_vpd_entry(const int port)
-{
- int cc1;
- int cc2;
- print_current_state(port);
-
- /* Get power from VCONN */
- vpd_vconn_pwr_sel_odl(PWR_VCONN);
-
- /*
- * Detect which of the Charge-Through port’s CC1 or CC2
- * pins is connected through the cable
- */
- vpd_ct_get_cc(&cc1, &cc2);
- tc[port].ct_cc = cc_is_rp(cc2) ? CT_CC2 : CT_CC1;
-
- /*
- * 1. Remove or reduce any additional capacitance on the
- * Host-side CC port
- */
- vpd_mcu_cc_en(0);
-
- /*
- * 2. Disable the Rp termination advertising 3.0 A on the
- * host port’s CC pin
- */
- vpd_host_set_pull(TYPEC_CC_OPEN, 0);
-
- /*
- * 3. Passively multiplex the detected Charge-Through port’s
- * CC pin through to the host port’s CC
- */
- vpd_ct_cc_sel(tc[port].ct_cc);
-
- /*
- * 4. Disable the Rd on the Charge-Through port’s CC1 and CC2
- * pins
- */
- vpd_ct_set_pull(TYPEC_CC_OPEN, 0);
-
- /*
- * 5. Connect the Charge-Through port’s VBUS through to the
- * host port’s VBUS
- */
- vpd_vbus_pass_en(1);
-
- tc[port].cc_state = PD_CC_UNSET;
-}
-
-static void tc_ct_attached_vpd_run(const int port)
-{
- int new_cc_state;
- int cc1;
- int cc2;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTDisabled.VPD if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state_tc(port, TC_CT_DISABLED_VPD);
- return;
- }
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
- if ((tc[port].ct_cc ? cc2 : cc1) == TYPEC_CC_VOLT_OPEN)
- new_cc_state = PD_CC_NONE;
- else
- new_cc_state = PD_CC_DFP_ATTACHED;
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val + PD_T_VPDCTDD;
- return;
- }
-
- if (get_time().val < tc[port].pd_debounce)
- return;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTUnattached.VPD when VBUS falls below vSinkDisconnect and the
- * state of the passed-through CC pin is SNK.Open for tVPDCTDD.
- */
- if (tc[port].cc_state == PD_CC_NONE && !vpd_is_ct_vbus_present())
- set_state_tc(port, TC_CT_UNATTACHED_VPD);
-}
-
-/**
- * CTAttachWait.VPD
- *
- * Super State Entry Actions:
- * Isolate the Host-side port from the Charge-Through port
- * Enable mcu communication
- * Place RP3A0 on Host CC
- * Connect Charge-Through Rd
- * Get power from VCONN
- */
-static void tc_ct_attach_wait_vpd_entry(const int port)
-{
- print_current_state(port);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- pd_set_polarity(port, 0);
-
- tc[port].cc_state = PD_CC_UNSET;
-}
-
-static void tc_ct_attach_wait_vpd_run(const int port)
-{
- int new_cc_state;
- int cc1;
- int cc2;
-
- /* Check CT CC for connection */
- vpd_ct_get_cc(&cc1, &cc2);
-
- if (cc_is_rp(cc1) != cc_is_rp(cc2))
- new_cc_state = PD_CC_DFP_ATTACHED;
- else if (!cc_is_rp(cc1) && !cc_is_rp(cc2))
- new_cc_state = PD_CC_NONE;
- else
- new_cc_state = PD_CC_UNSET;
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTDisabled.VPD if VCONN falls below vVCONNDisconnect.
- */
- if (!vpd_is_vconn_present()) {
- set_state_tc(port, TC_CT_DISABLED_VPD);
- return;
- }
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_state = new_cc_state;
- tc[port].cc_debounce = get_time().val +
- PD_T_CC_DEBOUNCE;
- tc[port].pd_debounce = get_time().val +
- PD_T_PD_DEBOUNCE;
- return;
- }
-
- if (get_time().val > tc[port].pd_debounce) {
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition
- * to CTUnattached.VPD when the state of both the Charge-Through
- * port’s CC1 and CC2 pins are SNK.Open for at least
- * tPDDebounce.
- */
- if (tc[port].cc_state == PD_CC_NONE) {
- set_state_tc(port, TC_CT_UNATTACHED_VPD);
- return;
- }
- }
-
- if (get_time().val > tc[port].cc_debounce) {
- /*
- * A Charge-Through VCONN-Powered USB Device shall transition to
- * CTAttached.VPD after the state of only one of the
- * Charge-Through port’s CC1 or CC2 pins is SNK.Rp for at
- * least tCCDebounce and VBUS on the Charge-Through port is
- * detected.
- */
- if (tc[port].cc_state == PD_CC_DFP_ATTACHED &&
- vpd_is_ct_vbus_present()) {
- set_state_tc(port, TC_CT_ATTACHED_VPD);
- return;
- }
- }
-}
-
-static void tc_ct_attach_wait_vpd_exit(const int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
-}
-
-/**
- * Super State HOST_RP3_CT_RD
- */
-static void tc_host_rp3_ct_rd_entry(const int port)
-{
- /* Place RP3A0 on Host CC */
- vpd_host_set_pull(TYPEC_CC_RP, TYPEC_RP_3A0);
-
- /* Connect Charge-Through Rd */
- vpd_ct_set_pull(TYPEC_CC_RD, 0);
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall
- * ensure that it is powered by VCONN
- */
-
- /* Make sure vconn is on */
- if (!vpd_is_vconn_present())
- set_state_tc(port, TC_ERROR_RECOVERY);
-
- /* Get power from VCONN */
- vpd_vconn_pwr_sel_odl(PWR_VCONN);
-}
-
-/**
- * Super State HOST_RP3_CT_RPU
- */
-static void tc_host_rp3_ct_rpu_entry(const int port)
-{
- /* Place RP3A0 on Host CC */
- vpd_host_set_pull(TYPEC_CC_RP, TYPEC_RP_3A0);
-
- /* Place RPUSB on Charge-Through CC */
- vpd_ct_set_pull(TYPEC_CC_RP, TYPEC_RP_USB);
-
- /*
- * A Charge-Through VCONN-Powered USB Device shall
- * ensure that it is powered by VCONN
- */
-
- /* Make sure vconn is on */
- if (!vpd_is_vconn_present())
- set_state_tc(port, TC_ERROR_RECOVERY);
-
- /* Get power from VCONN */
- vpd_vconn_pwr_sel_odl(PWR_VCONN);
-}
-
-/* All necessary Type-C states */
-
-/*
- * Type-C State Hierarchy (Sub-States are listed inside the boxes)
- *
- * | TC_VBUS_CC_ISO ------------------------------------------------------|
- * | |
- * | | TC_HOST_RARD_CT_RD -----------| | TC_HOST_OPEN_CT_OPEN ---------| |
- * | | | | | |
- * | | TC_UNATTACHED_SNK | | TC_DISABLED | |
- * | | TC_ATTACH_WAIT_SNK | | TC_ERROR_RECOVERY | |
- * | | TC_TRY_SNK | |-------------------------------| |
- * | |-------------------------------| |
- * | |
- * | | TC_HOST_RP3_CT_RD ------------| | TC_HOST_RPU_CT_RD ------------| |
- * | | | | | |
- * | | TC_CT_TRY_SNK | | TC_UNATTACHED_SRC | |
- * | | TC_CT_UNATTACHED_VPD | | TC_ATTACH_WAIT_SRC | |
- * | | TC_CT_ATTACH_WAIT_VPD | | TC_TRY_WAIT_SR | |
- * | |-------------------------------| |-------------------------------| |
- * | |
- * | | TC_HOST_RP3_CT_RPU -----------| |
- * | | | |
- * | | TC_CT_ATTACH_WAIT_UNSUPPORTED | |
- * | | TC_CT_ATTACHED_UNSUPPORTED | |
- * | | TC_CT_UNATTACHED_UNSUPPORTED | |
- * | |-------------------------------| |
- * |----------------------------------------------------------------------|
- *
- * TC_ATTACHED_SNK
- * TC_ATTACHED_SRC
- * TC_CT_ATTACHED_VPD
- *
- */
-static const struct usb_state tc_states[] = {
- /* Super States */
- [TC_VBUS_CC_ISO] = {
- .entry = tc_vbus_cc_iso_entry,
- },
- [TC_HOST_RARD_CT_RD] = {
- .entry = tc_host_rard_ct_rd_entry,
- .parent = &tc_states[TC_VBUS_CC_ISO],
- },
- [TC_HOST_OPEN_CT_OPEN] = {
- .entry = tc_host_open_ct_open_entry,
- .parent = &tc_states[TC_VBUS_CC_ISO],
- },
- [TC_HOST_RP3_CT_RD] = {
- .entry = tc_host_rp3_ct_rd_entry,
- .parent = &tc_states[TC_VBUS_CC_ISO],
- },
- [TC_HOST_RP3_CT_RPU] = {
- .entry = tc_host_rp3_ct_rpu_entry,
- .parent = &tc_states[TC_VBUS_CC_ISO],
- },
- [TC_HOST_RPU_CT_RD] = {
- .entry = tc_host_rpu_ct_rd_entry,
- .parent = &tc_states[TC_VBUS_CC_ISO],
- },
- /* Normal States */
- [TC_DISABLED] = {
- .entry = tc_disabled_entry,
- .run = tc_disabled_run,
- .exit = tc_disabled_exit,
- .parent = &tc_states[TC_HOST_OPEN_CT_OPEN],
- },
- [TC_UNATTACHED_SNK] = {
- .entry = tc_unattached_snk_entry,
- .run = tc_unattached_snk_run,
- .parent = &tc_states[TC_HOST_RARD_CT_RD],
- },
- [TC_ATTACH_WAIT_SNK] = {
- .entry = tc_attach_wait_snk_entry,
- .run = tc_attach_wait_snk_run,
- .parent = &tc_states[TC_HOST_RARD_CT_RD],
- },
- [TC_ATTACHED_SNK] = {
- .entry = tc_attached_snk_entry,
- .run = tc_attached_snk_run,
- .exit = tc_attached_snk_exit,
- },
- [TC_ERROR_RECOVERY] = {
- .entry = tc_error_recovery_entry,
- .run = tc_error_recovery_run,
- .parent = &tc_states[TC_HOST_OPEN_CT_OPEN],
- },
- [TC_TRY_SNK] = {
- .entry = tc_try_snk_entry,
- .run = tc_try_snk_run,
- .parent = &tc_states[TC_HOST_RARD_CT_RD],
- },
- [TC_UNATTACHED_SRC] = {
- .entry = tc_unattached_src_entry,
- .run = tc_unattached_src_run,
- .parent = &tc_states[TC_HOST_RPU_CT_RD],
- },
- [TC_ATTACH_WAIT_SRC] = {
- .entry = tc_attach_wait_src_entry,
- .run = tc_attach_wait_src_run,
- .parent = &tc_states[TC_HOST_RPU_CT_RD],
- },
- [TC_TRY_WAIT_SRC] = {
- .entry = tc_try_wait_src_entry,
- .run = tc_try_wait_src_run,
- .parent = &tc_states[TC_HOST_RPU_CT_RD],
- },
- [TC_ATTACHED_SRC] = {
- .entry = tc_attached_src_entry,
- .run = tc_attached_src_run,
- },
- [TC_CT_TRY_SNK] = {
- .entry = tc_ct_try_snk_entry,
- .run = tc_ct_try_snk_run,
- .exit = tc_ct_try_snk_exit,
- .parent = &tc_states[TC_HOST_RP3_CT_RD],
- },
- [TC_CT_ATTACH_WAIT_UNSUPPORTED] = {
- .entry = tc_ct_attach_wait_unsupported_entry,
- .run = tc_ct_attach_wait_unsupported_run,
- .exit = tc_ct_attach_wait_unsupported_exit,
- .parent = &tc_states[TC_HOST_RP3_CT_RPU],
- },
- [TC_CT_ATTACHED_UNSUPPORTED] = {
- .entry = tc_ct_attached_unsupported_entry,
- .run = tc_ct_attached_unsupported_run,
- .exit = tc_ct_attached_unsupported_exit,
- .parent = &tc_states[TC_HOST_RP3_CT_RPU],
- },
- [TC_CT_UNATTACHED_UNSUPPORTED] = {
- .entry = tc_ct_unattached_unsupported_entry,
- .run = tc_ct_unattached_unsupported_run,
- .exit = tc_ct_unattached_unsupported_exit,
- .parent = &tc_states[TC_HOST_RP3_CT_RPU],
- },
- [TC_CT_UNATTACHED_VPD] = {
- .entry = tc_ct_unattached_vpd_entry,
- .run = tc_ct_unattached_vpd_run,
- .exit = tc_ct_unattached_vpd_exit,
- .parent = &tc_states[TC_HOST_RP3_CT_RD],
- },
- [TC_CT_DISABLED_VPD] = {
- .entry = tc_ct_disabled_vpd_entry,
- .run = tc_ct_disabled_vpd_run,
- .parent = &tc_states[TC_HOST_OPEN_CT_OPEN],
- },
- [TC_CT_ATTACHED_VPD] = {
- .entry = tc_ct_attached_vpd_entry,
- .run = tc_ct_attached_vpd_run,
- },
- [TC_CT_ATTACH_WAIT_VPD] = {
- .entry = tc_ct_attach_wait_vpd_entry,
- .run = tc_ct_attach_wait_vpd_run,
- .exit = tc_ct_attach_wait_vpd_exit,
- .parent = &tc_states[TC_HOST_RP3_CT_RD],
- },
-};
-
-#ifdef TEST_BUILD
-const struct test_sm_data test_tc_sm_data[] = {
- {
- .base = tc_states,
- .size = ARRAY_SIZE(tc_states),
- .names = tc_state_names,
- .names_size = ARRAY_SIZE(tc_state_names),
- },
-};
-const int test_tc_sm_data_size = ARRAY_SIZE(test_tc_sm_data);
-#endif
diff --git a/common/usbc/usb_tc_drp_acc_trysrc_sm.c b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
deleted file mode 100644
index 182ea686ec..0000000000
--- a/common/usbc/usb_tc_drp_acc_trysrc_sm.c
+++ /dev/null
@@ -1,4160 +0,0 @@
-/* Copyright 2019 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.
- */
-
-#include "charge_manager.h"
-#include "charge_state.h"
-#include "common.h"
-#include "console.h"
-#include "hooks.h"
-#include "system.h"
-#include "task.h"
-#include "tcpm/tcpm.h"
-#include "usb_common.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "usb_pd_dpm.h"
-#include "usb_pd_tcpm.h"
-#include "usb_pd_timer.h"
-#include "usb_pe_sm.h"
-#include "usb_prl_sm.h"
-#include "usb_sm.h"
-#include "usb_tc_sm.h"
-#include "usbc_ocp.h"
-#include "usbc_ppc.h"
-#include "vboot.h"
-
-/*
- * USB Type-C DRP with Accessory and Try.SRC module
- * See Figure 4-16 in Release 1.4 of USB Type-C Spec.
- */
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#else /* CONFIG_COMMON_RUNTIME */
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif
-
-#define CPRINTF_LX(x, format, args...) \
- do { \
- if (tc_debug_level >= x) \
- CPRINTF(format, ## args); \
- } while (0)
-#define CPRINTF_L1(format, args...) CPRINTF_LX(1, format, ## args)
-#define CPRINTF_L2(format, args...) CPRINTF_LX(2, format, ## args)
-#define CPRINTF_L3(format, args...) CPRINTF_LX(3, format, ## args)
-
-#define CPRINTS_LX(x, format, args...) \
- do { \
- if (tc_debug_level >= x) \
- CPRINTS(format, ## args); \
- } while (0)
-#define CPRINTS_L1(format, args...) CPRINTS_LX(1, format, ## args)
-#define CPRINTS_L2(format, args...) CPRINTS_LX(2, format, ## args)
-#define CPRINTS_L3(format, args...) CPRINTS_LX(3, format, ## args)
-
-/*
- * Define DEBUG_PRINT_FLAG_AND_EVENT_NAMES to print flag names when set and
- * cleared, and event names when handled by tc_event_check().
- */
-#undef DEBUG_PRINT_FLAG_AND_EVENT_NAMES
-
-#ifdef DEBUG_PRINT_FLAG_AND_EVENT_NAMES
-void print_flag(int port, int set_or_clear, int flag);
-#define TC_SET_FLAG(port, flag) \
- do { \
- print_flag(port, 1, flag); \
- atomic_or(&tc[port].flags, (flag)); \
- } while (0)
-#define TC_CLR_FLAG(port, flag) \
- do { \
- print_flag(port, 0, flag); \
- atomic_clear_bits(&tc[port].flags, (flag)); \
- } while (0)
-#else
-#define TC_SET_FLAG(port, flag) atomic_or(&tc[port].flags, (flag))
-#define TC_CLR_FLAG(port, flag) atomic_clear_bits(&tc[port].flags, (flag))
-#endif
-#define TC_CHK_FLAG(port, flag) (tc[port].flags & (flag))
-
-/* Type-C Layer Flags */
-/* Flag to note we are sourcing VCONN */
-#define TC_FLAGS_VCONN_ON BIT(0)
-/* Flag to note port partner has Rp/Rp or Rd/Rd */
-#define TC_FLAGS_TS_DTS_PARTNER BIT(1)
-/* Flag to note VBus input has never been low */
-#define TC_FLAGS_VBUS_NEVER_LOW BIT(2)
-/* Flag to note Low Power Mode transition is currently happening */
-#define TC_FLAGS_LPM_TRANSITION BIT(3)
-/* Flag to note Low Power Mode is currently on */
-#define TC_FLAGS_LPM_ENGAGED BIT(4)
-/* Flag to note CVTPD has been detected */
-#define TC_FLAGS_CTVPD_DETECTED BIT(5)
-/* Flag to note request to swap to VCONN on */
-#define TC_FLAGS_REQUEST_VC_SWAP_ON BIT(6)
-/* Flag to note request to swap to VCONN off */
-#define TC_FLAGS_REQUEST_VC_SWAP_OFF BIT(7)
-/* Flag to note request to swap VCONN is being rejected */
-#define TC_FLAGS_REJECT_VCONN_SWAP BIT(8)
-/* Flag to note request to power role swap */
-#define TC_FLAGS_REQUEST_PR_SWAP BIT(9)
-/* Flag to note request to data role swap */
-#define TC_FLAGS_REQUEST_DR_SWAP BIT(10)
-/* Flag to note request to power off sink */
-#define TC_FLAGS_POWER_OFF_SNK BIT(11)
-/* Flag to note port partner is Power Delivery capable */
-#define TC_FLAGS_PARTNER_PD_CAPABLE BIT(12)
-/* Flag to note hard reset has been requested */
-#define TC_FLAGS_HARD_RESET_REQUESTED BIT(13)
-/* Flag to note we are currently performing PR Swap */
-#define TC_FLAGS_PR_SWAP_IN_PROGRESS BIT(14)
-/* Flag to note we should check for connection */
-#define TC_FLAGS_CHECK_CONNECTION BIT(15)
-/* Flag to note request from pd_set_suspend to enter TC_DISABLED state */
-#define TC_FLAGS_REQUEST_SUSPEND BIT(16)
-/* Flag to note we are in TC_DISABLED state */
-#define TC_FLAGS_SUSPENDED BIT(17)
-/* Flag to indicate the port current limit has changed */
-#define TC_FLAGS_UPDATE_CURRENT BIT(18)
-/* Flag to indicate USB mux should be updated */
-#define TC_FLAGS_UPDATE_USB_MUX BIT(19)
-/* Flag for retimer firmware update */
-#define TC_FLAGS_USB_RETIMER_FW_UPDATE_RUN BIT(20)
-#define TC_FLAGS_USB_RETIMER_FW_UPDATE_LTD_RUN BIT(21)
-/* Flag for asynchronous call to request Error Recovery */
-#define TC_FLAGS_REQUEST_ERROR_RECOVERY BIT(22)
-
-/* For checking flag_bit_names[] array */
-#define TC_FLAGS_COUNT 23
-
-/* On disconnect, clear most of the flags. */
-#define CLR_FLAGS_ON_DISCONNECT(port) TC_CLR_FLAG(port, \
- ~(TC_FLAGS_LPM_ENGAGED | TC_FLAGS_REQUEST_SUSPEND | TC_FLAGS_SUSPENDED))
-
-/*
- * 10 ms is enough time for any TCPC transaction to complete
- *
- * This value must be below ~39.7 ms to put ANX7447 into LPM due to bug in
- * silicon (see b/77544959 and b/149761477 for more details).
- */
-#define PD_LPM_DEBOUNCE_US (10 * MSEC)
-
-/*
- * This delay is not part of the USB Type-C specification or the USB port
- * controller specification. Some TCPCs require extra time before the CC_STATUS
- * register is updated when exiting low power mode.
- *
- * This delay can be possibly shortened or removed by checking VBUS state
- * before trying to re-enter LPM.
- *
- * TODO(b/162347811): TCPMv2: Wait for debounce on Vbus and CC lines
- */
-#define PD_LPM_EXIT_DEBOUNCE_US CONFIG_USB_PD_TCPC_LPM_EXIT_DEBOUNCE
-
-/*
- * The TypeC state machine uses this bit to disable/enable PD
- * This bit corresponds to bit-0 of pd_disabled_mask
- */
-#define PD_DISABLED_NO_CONNECTION BIT(0)
-/*
- * Console and Host commands use this bit to override the
- * PD_DISABLED_NO_CONNECTION bit that was set by the TypeC
- * state machine.
- * This bit corresponds to bit-1 of pd_disabled_mask
- */
-#define PD_DISABLED_BY_POLICY BIT(1)
-
-/* Unreachable time in future */
-#define TIMER_DISABLED 0xffffffffffffffff
-
-enum ps_reset_sequence {
- PS_STATE0,
- PS_STATE1,
- PS_STATE2,
-};
-
-/* List of all TypeC-level states */
-enum usb_tc_state {
- /* Super States */
- TC_CC_OPEN,
- TC_CC_RD,
- TC_CC_RP,
- /* Normal States */
- TC_DISABLED,
- TC_ERROR_RECOVERY,
- TC_UNATTACHED_SNK,
- TC_ATTACH_WAIT_SNK,
- TC_ATTACHED_SNK,
- TC_UNATTACHED_SRC,
- TC_ATTACH_WAIT_SRC,
- TC_ATTACHED_SRC,
- TC_TRY_SRC,
- TC_TRY_WAIT_SNK,
- TC_DRP_AUTO_TOGGLE,
- TC_LOW_POWER_MODE,
- TC_CT_UNATTACHED_SNK,
- TC_CT_ATTACHED_SNK,
-
- TC_STATE_COUNT,
-};
-/* Forward declare the full list of states. This is indexed by usb_tc_state */
-static const struct usb_state tc_states[];
-
-/*
- * Remove all of the states that aren't support at link time. This allows
- * IS_ENABLED to work.
- */
-#ifndef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
-GEN_NOT_SUPPORTED(TC_DRP_AUTO_TOGGLE);
-#define TC_DRP_AUTO_TOGGLE TC_DRP_AUTO_TOGGLE_NOT_SUPPORTED
-#endif /* CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE */
-
-#ifndef CONFIG_USB_PD_TCPC_LOW_POWER
-GEN_NOT_SUPPORTED(TC_LOW_POWER_MODE);
-#define TC_LOW_POWER_MODE TC_LOW_POWER_MODE_NOT_SUPPORTED
-#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */
-
-#ifndef CONFIG_USB_PE_SM
-GEN_NOT_SUPPORTED(TC_CT_UNATTACHED_SNK);
-#define TC_CT_UNATTACHED_SNK TC_CT_UNATTACHED_SNK_NOT_SUPPORTED
-GEN_NOT_SUPPORTED(TC_CT_ATTACHED_SNK);
-#define TC_CT_ATTACHED_SNK TC_CT_ATTACHED_SNK_NOT_SUPPORTED
-#endif /* CONFIG_USB_PE_SM */
-
-/*
- * If CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT is not defined then
- * _GPIO_CCD_MODE_ODL is not needed. Declare as extern so IS_ENABLED will work.
- */
-#ifndef CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT
-extern int _GPIO_CCD_MODE_ODL;
-#else
-#define _GPIO_CCD_MODE_ODL GPIO_CCD_MODE_ODL
-#endif /* CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT */
-
-/*
- * We will use DEBUG LABELS if we will be able to print (COMMON RUNTIME)
- * and either CONFIG_USB_PD_DEBUG_LEVEL is not defined (no override) or
- * we are overriding and the level is not DISABLED.
- *
- * If we can't print or the CONFIG_USB_PD_DEBUG_LEVEL is defined to be 0
- * then the DEBUG LABELS will be removed from the build.
- */
-#if defined(CONFIG_COMMON_RUNTIME) && \
- (!defined(CONFIG_USB_PD_DEBUG_LEVEL) || \
- (CONFIG_USB_PD_DEBUG_LEVEL > 0))
-#define USB_PD_DEBUG_LABELS
-#endif
-
-/*
- * Helper Macro to determine if the machine is in state
- * TC_ATTACHED_SRC
- */
-#define IS_ATTACHED_SRC(port) (get_state_tc(port) == TC_ATTACHED_SRC)
-
-/*
- * Helper Macro to determine if the machine is in state
- * TC_ATTACHED_SNK
- */
-#define IS_ATTACHED_SNK(port) (get_state_tc(port) == TC_ATTACHED_SNK)
-
-
-/* List of human readable state names for console debugging */
-__maybe_unused static __const_data const char * const tc_state_names[] = {
-#ifdef USB_PD_DEBUG_LABELS
- [TC_DISABLED] = "Disabled",
- [TC_ERROR_RECOVERY] = "ErrorRecovery",
- [TC_UNATTACHED_SNK] = "Unattached.SNK",
- [TC_ATTACH_WAIT_SNK] = "AttachWait.SNK",
- [TC_ATTACHED_SNK] = "Attached.SNK",
- [TC_UNATTACHED_SRC] = "Unattached.SRC",
- [TC_ATTACH_WAIT_SRC] = "AttachWait.SRC",
- [TC_ATTACHED_SRC] = "Attached.SRC",
- [TC_TRY_SRC] = "Try.SRC",
- [TC_TRY_WAIT_SNK] = "TryWait.SNK",
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- [TC_DRP_AUTO_TOGGLE] = "DRPAutoToggle",
-#endif
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- [TC_LOW_POWER_MODE] = "LowPowerMode",
-#endif
-#ifdef CONFIG_USB_PE_SM
- [TC_CT_UNATTACHED_SNK] = "CTUnattached.SNK",
- [TC_CT_ATTACHED_SNK] = "CTAttached.SNK",
-#endif
- /* Super States */
- [TC_CC_OPEN] = "SS:CC_OPEN",
- [TC_CC_RD] = "SS:CC_RD",
- [TC_CC_RP] = "SS:CC_RP",
-
- [TC_STATE_COUNT] = "",
-#endif
-};
-
-/* Debug log level - higher number == more log */
-#ifdef CONFIG_USB_PD_DEBUG_LEVEL
-static const enum debug_level tc_debug_level = CONFIG_USB_PD_DEBUG_LEVEL;
-#else
-static enum debug_level tc_debug_level = DEBUG_LEVEL_1;
-#endif
-
-#ifdef DEBUG_PRINT_FLAG_AND_EVENT_NAMES
-struct bit_name {
- int value;
- const char *name;
-};
-
-static struct bit_name flag_bit_names[] = {
- { TC_FLAGS_VCONN_ON, "VCONN_ON" },
- { TC_FLAGS_TS_DTS_PARTNER, "TS_DTS_PARTNER" },
- { TC_FLAGS_VBUS_NEVER_LOW, "VBUS_NEVER_LOW" },
- { TC_FLAGS_LPM_TRANSITION, "LPM_TRANSITION" },
- { TC_FLAGS_LPM_ENGAGED, "LPM_ENGAGED" },
- { TC_FLAGS_CTVPD_DETECTED, "CTVPD_DETECTED" },
- { TC_FLAGS_REQUEST_VC_SWAP_ON, "REQUEST_VC_SWAP_ON" },
- { TC_FLAGS_REQUEST_VC_SWAP_OFF, "REQUEST_VC_SWAP_OFF" },
- { TC_FLAGS_REJECT_VCONN_SWAP, "REJECT_VCONN_SWAP" },
- { TC_FLAGS_REQUEST_PR_SWAP, "REQUEST_PR_SWAP" },
- { TC_FLAGS_REQUEST_DR_SWAP, "REQUEST_DR_SWAP" },
- { TC_FLAGS_POWER_OFF_SNK, "POWER_OFF_SNK" },
- { TC_FLAGS_PARTNER_PD_CAPABLE, "PARTNER_PD_CAPABLE" },
- { TC_FLAGS_HARD_RESET_REQUESTED, "HARD_RESET_REQUESTED" },
- { TC_FLAGS_PR_SWAP_IN_PROGRESS, "PR_SWAP_IN_PROGRESS" },
- { TC_FLAGS_CHECK_CONNECTION, "CHECK_CONNECTION" },
- { TC_FLAGS_REQUEST_SUSPEND, "REQUEST_SUSPEND" },
- { TC_FLAGS_SUSPENDED, "SUSPENDED" },
- { TC_FLAGS_UPDATE_CURRENT, "UPDATE_CURRENT" },
- { TC_FLAGS_UPDATE_USB_MUX, "UPDATE_USB_MUX" },
- { TC_FLAGS_USB_RETIMER_FW_UPDATE_RUN,
- "USB_RETIMER_FW_UPDATE_RUN" },
- { TC_FLAGS_USB_RETIMER_FW_UPDATE_LTD_RUN,
- "USB_RETIMER_FW_UPDATE_LTD_RUN" },
- { TC_FLAGS_REQUEST_ERROR_RECOVERY, "REQUEST_ERROR_RECOCVERY"},
-};
-BUILD_ASSERT(ARRAY_SIZE(flag_bit_names) == TC_FLAGS_COUNT);
-
-static struct bit_name event_bit_names[] = {
- { TASK_EVENT_SYSJUMP_READY, "SYSJUMP_READY" },
- { TASK_EVENT_IPC_READY, "IPC_READY" },
- { TASK_EVENT_PD_AWAKE, "PD_AWAKE" },
- { TASK_EVENT_PECI_DONE, "PECI_DONE" },
- { TASK_EVENT_I2C_IDLE, "I2C_IDLE" },
-#ifdef TASK_EVENT_PS2_DONE
- { TASK_EVENT_PS2_DONE, "PS2_DONE" },
-#endif
- { TASK_EVENT_DMA_TC, "DMA_TC" },
- { TASK_EVENT_ADC_DONE, "ADC_DONE" },
- { TASK_EVENT_RESET_DONE, "RESET_DONE" },
- { TASK_EVENT_WAKE, "WAKE" },
- { TASK_EVENT_MUTEX, "MUTEX" },
- { TASK_EVENT_TIMER, "TIMER" },
- { PD_EVENT_TX, "TX" },
- { PD_EVENT_CC, "CC" },
- { PD_EVENT_TCPC_RESET, "TCPC_RESET" },
- { PD_EVENT_UPDATE_DUAL_ROLE, "UPDATE_DUAL_ROLE" },
- { PD_EVENT_DEVICE_ACCESSED, "DEVICE_ACCESSED" },
- { PD_EVENT_POWER_STATE_CHANGE, "POWER_STATE_CHANGE" },
- { PD_EVENT_SEND_HARD_RESET, "SEND_HARD_RESET" },
- { PD_EVENT_SYSJUMP, "SYSJUMP" },
-};
-
-static void print_bits(int port, const char *desc, int value,
- struct bit_name *names, int names_size)
-{
- int i;
-
- CPRINTF("C%d: %s 0x%x : ", port, desc, value);
- for (i = 0; i < names_size; i++) {
- if (value & names[i].value)
- CPRINTF("%s | ", names[i].name);
- value &= ~names[i].value;
- }
- if (value != 0)
- CPRINTF("0x%x", value);
- CPRINTF("\n");
-}
-
-void print_flag(int port, int set_or_clear, int flag)
-{
- print_bits(port, set_or_clear ? "Set" : "Clr", flag, flag_bit_names,
- ARRAY_SIZE(flag_bit_names));
-}
-#endif /* DEBUG_PRINT_FLAG_AND_EVENT_NAMES */
-
-#ifndef CONFIG_USB_PD_TRY_SRC
-extern int TC_TRY_SRC_UNDEFINED;
-extern int TC_TRY_WAIT_SNK_UNDEFINED;
-#define TC_TRY_SRC TC_TRY_SRC_UNDEFINED
-#define TC_TRY_WAIT_SNK TC_TRY_WAIT_SNK_UNDEFINED
-#endif
-
-static struct type_c {
- /* state machine context */
- struct sm_ctx ctx;
- /* current port power role (SOURCE or SINK) */
- enum pd_power_role power_role;
- /* current port data role (DFP or UFP) */
- enum pd_data_role data_role;
- /*
- * Higher-level power deliver state machines are enabled if false,
- * else they're disabled if bits PD_DISABLED_NO_CONNECTION or
- * PD_DISABLED_BY_POLICY are set.
- */
- uint32_t pd_disabled_mask;
- /*
- * Timer for handling TOGGLE_OFF/FORCE_SINK mode when auto-toggle
- * enabled. See drp_auto_toggle_next_state() for details.
- */
- uint64_t drp_sink_time;
-#ifdef CONFIG_USB_PE_SM
- /* Power supply reset sequence during a hard reset */
- enum ps_reset_sequence ps_reset_state;
-#endif
- /* Port polarity */
- enum tcpc_cc_polarity polarity;
- /* port flags, see TC_FLAGS_* */
- uint32_t flags;
- /* The cc state */
- enum pd_cc_states cc_state;
- /* Tasks to notify after TCPC has been reset */
- int tasks_waiting_on_reset;
- /* Tasks preventing TCPC from entering low power mode */
- int tasks_preventing_lpm;
- /* Voltage on CC pin */
- enum tcpc_cc_voltage_status cc_voltage;
- /* Type-C current */
- typec_current_t typec_curr;
- /* Type-C current change */
- typec_current_t typec_curr_change;
-
- /* Selected TCPC CC/Rp values */
- enum tcpc_cc_pull select_cc_pull;
- enum tcpc_rp_value select_current_limit_rp;
- enum tcpc_rp_value select_collision_rp;
-} tc[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* Port dual-role state */
-static volatile __maybe_unused
-enum pd_dual_role_states drp_state[CONFIG_USB_PD_PORT_MAX_COUNT] = {
- [0 ... (CONFIG_USB_PD_PORT_MAX_COUNT - 1)] =
- CONFIG_USB_PD_INITIAL_DRP_STATE};
-
-static void set_vconn(int port, int enable);
-
-/* Forward declare common, private functions */
-static __maybe_unused int reset_device_and_notify(int port);
-static __maybe_unused void check_drp_connection(const int port);
-static void sink_power_sub_states(int port);
-static void set_ccd_mode(int port, bool enable);
-
-__maybe_unused static void handle_new_power_state(int port);
-
-static void pd_update_dual_role_config(int port);
-
-/* Forward declare common, private functions */
-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 volatile enum try_src_override_t pd_try_src_override;
-static void pd_update_try_source(void);
-
-static void sink_stop_drawing_current(int port);
-
-__maybe_unused static bool is_try_src_enabled(int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_TRY_SRC))
- assert(0);
-
- return ((pd_try_src_override == TRY_SRC_OVERRIDE_ON) ||
- (pd_try_src_override == TRY_SRC_NO_OVERRIDE && pd_try_src));
-}
-
-/*
- * Public Functions
- *
- * NOTE: Functions prefixed with pd_ are defined in usb_pd.h
- * Functions prefixed with tc_ are defined int usb_tc_sm.h
- */
-
-#ifndef CONFIG_USB_PRL_SM
-
-/*
- * These pd_ functions are implemented in common/usb_prl_sm.c
- */
-
-void pd_transmit_complete(int port, int status)
-{
- /* DO NOTHING */
-}
-
-void pd_execute_hard_reset(int port)
-{
- /* DO NOTHING */
-}
-
-__overridable void pd_set_vbus_discharge(int port, int enable)
-{
- /* DO NOTHING */
-}
-
-#endif /* !CONFIG_USB_PRL_SM */
-
-#ifndef CONFIG_USB_PE_SM
-
-/*
- * These pd_ functions are implemented in the PE layer
- */
-const uint32_t * const pd_get_src_caps(int port)
-{
- return NULL;
-}
-
-uint8_t pd_get_src_cap_cnt(int port)
-{
- return 0;
-}
-
-const uint32_t * const pd_get_snk_caps(int port)
-{
- return NULL;
-}
-
-uint8_t pd_get_snk_cap_cnt(int port)
-{
- return 0;
-}
-
-void pd_set_src_caps(int port, int cnt, uint32_t *src_caps)
-{
-}
-
-int pd_get_rev(int port, enum tcpci_msg_type type)
-{
- return PD_REV30;
-}
-
-#endif /* !CONFIG_USB_PR_SM */
-
-#ifndef HAS_TASK_CHIPSET
-__overridable enum pd_dual_role_states board_tc_get_initial_drp_mode(int port)
-{
- /*
- * DRP state is typically adjusted as the chipset state is changed. For
- * projects which don't include an AP this function can be used for to
- * specify what the starting DRP state should be.
- */
- return PD_DRP_FORCE_SINK;
-}
-#endif
-
-void pd_update_contract(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- if (IS_ATTACHED_SRC(port))
- pd_dpm_request(port, DPM_REQUEST_SRC_CAP_CHANGE);
- }
-}
-
-void pd_request_source_voltage(int port, int mv)
-{
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- pd_set_max_voltage(mv);
-
- if (IS_ATTACHED_SNK(port))
- pd_dpm_request(port, DPM_REQUEST_NEW_POWER_LEVEL);
- else
- pd_dpm_request(port, DPM_REQUEST_PR_SWAP);
-
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-void pd_set_external_voltage_limit(int port, int mv)
-{
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- pd_set_max_voltage(mv);
-
- /* Must be in Attached.SNK when this function is called */
- if (get_state_tc(port) == TC_ATTACHED_SNK)
- pd_dpm_request(port, DPM_REQUEST_NEW_POWER_LEVEL);
-
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-void pd_set_new_power_request(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- /* Must be in Attached.SNK when this function is called */
- if (get_state_tc(port) == TC_ATTACHED_SNK)
- pd_dpm_request(port, DPM_REQUEST_NEW_POWER_LEVEL);
- }
-}
-
-void tc_request_power_swap(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- /*
- * Must be in Attached.SRC or Attached.SNK
- */
- if (IS_ATTACHED_SRC(port) || IS_ATTACHED_SNK(port)) {
- TC_SET_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS);
-
- /* Let tc_pr_swap_complete start the Vbus debounce */
- pd_timer_disable(port, TC_TIMER_VBUS_DEBOUNCE);
- }
-
- /*
- * TCPCI Rev2 V1.1 4.4.5.4.4
- * Disconnect Detection by the Sink TCPC during a Connection
- *
- * Upon reception of or prior to transmitting a PR_Swap
- * message, the TCPM acting as a Sink shall disable the Sink
- * disconnect detection to retain PD message delivery when
- * Power Role Swap happens. Disable AutoDischargeDisconnect.
- */
- if (IS_ATTACHED_SNK(port))
- tcpm_enable_auto_discharge_disconnect(port, 0);
- }
-}
-
-/* Flag to indicate PD comm is disabled on init */
-static int pd_disabled_on_init;
-
-static void pd_update_pd_comm(void)
-{
- int i;
-
- /*
- * Some batteries take much longer time to report its SOC.
- * The init function disabled PD comm on startup. Need this
- * hook to enable PD comm when the battery level is enough.
- */
- if (pd_disabled_on_init && pd_is_battery_capable()) {
- for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++)
- pd_comm_enable(i, 1);
- pd_disabled_on_init = 0;
- }
-}
-DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, pd_update_pd_comm, HOOK_PRIO_DEFAULT);
-
-static bool pd_comm_allowed_by_policy(void)
-{
- if (system_is_in_rw())
- return true;
-
- if (vboot_allow_usb_pd())
- return true;
-
- /*
- * If enable PD in RO on a non-EFS2 device, a hard reset will be issued
- * when sysjump to RW that makes the device brownout on the dead-battery
- * case. Disable PD for this special case as a workaround.
- */
- if (!system_is_locked()) {
- if (IS_ENABLED(CONFIG_VBOOT_EFS2))
- return true;
-
- if (pd_is_battery_capable())
- return true;
-
- pd_disabled_on_init = 1;
- }
-
- return false;
-}
-
-static void tc_policy_pd_enable(int port, int en)
-{
- if (en)
- atomic_clear_bits(&tc[port].pd_disabled_mask,
- PD_DISABLED_BY_POLICY);
- else
- atomic_or(&tc[port].pd_disabled_mask, PD_DISABLED_BY_POLICY);
-
- CPRINTS("C%d: PD comm policy %sabled", port, en ? "en" : "dis");
-}
-
-static void tc_enable_pd(int port, int en)
-{
- if (en)
- atomic_clear_bits(&tc[port].pd_disabled_mask,
- PD_DISABLED_NO_CONNECTION);
- else
- atomic_or(&tc[port].pd_disabled_mask,
- PD_DISABLED_NO_CONNECTION);
-}
-
-__maybe_unused static void tc_enable_try_src(int en)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_TRY_SRC))
- assert(0);
-
- if (en)
- atomic_or(&pd_try_src, 1);
- else
- atomic_clear_bits(&pd_try_src, 1);
-}
-
-/*
- * Exit all modes due to a detach event
- * Note: this skips the ExitMode VDM steps in the PE because it is assumed the
- * partner is not present to receive them, and the PE will no longer be running.
- */
-static void tc_set_modes_exit(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PE_SM) &&
- 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);
- }
-}
-
-static void tc_detached(int port)
-{
- TC_CLR_FLAG(port, TC_FLAGS_TS_DTS_PARTNER);
- hook_notify(HOOK_USB_PD_DISCONNECT);
- tc_pd_connection(port, 0);
- tcpm_debug_accessory(port, 0);
- set_ccd_mode(port, 0);
- tc_set_modes_exit(port);
- if (IS_ENABLED(CONFIG_USB_PRL_SM))
- prl_set_default_pd_revision(port);
-
- /* Clear any mux connection on detach */
- if (IS_ENABLED(CONFIG_USBC_SS_MUX))
- usb_mux_set(port, USB_PD_MUX_NONE,
- USB_SWITCH_DISCONNECT, tc[port].polarity);
-}
-
-static inline void pd_set_dual_role_and_event(int port,
- enum pd_dual_role_states state, uint32_t event)
-{
- drp_state[port] = state;
-
- if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC))
- pd_update_try_source();
-
- if (event != 0)
- task_set_event(PD_PORT_TO_TASK_ID(port), event);
-}
-
-void pd_set_dual_role(int port, enum pd_dual_role_states state)
-{
- pd_set_dual_role_and_event(port, state, PD_EVENT_UPDATE_DUAL_ROLE);
-}
-
-int pd_comm_is_enabled(int port)
-{
- return tc_get_pd_enabled(port);
-}
-
-void pd_request_data_swap(int port)
-{
- /*
- * Must be in Attached.SRC, Attached.SNK, DebugAccessory.SNK,
- * or UnorientedDebugAccessory.SRC when this function
- * is called
- */
- if (IS_ATTACHED_SRC(port) || IS_ATTACHED_SNK(port)) {
- TC_SET_FLAG(port, TC_FLAGS_REQUEST_DR_SWAP);
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-/* Return true if partner port is known to be PD capable. */
-bool pd_capable(int port)
-{
- return !!TC_CHK_FLAG(port, TC_FLAGS_PARTNER_PD_CAPABLE);
-}
-
-/*
- * Return true if we transition through Unattached.SNK, but we're still waiting
- * to receive source caps from the partner. This indicates that the PD
- * capabilities are not yet known.
- */
-bool pd_waiting_on_partner_src_caps(int port)
-{
- return !pd_get_src_cap_cnt(port);
-}
-
-enum pd_dual_role_states pd_get_dual_role(int port)
-{
- return drp_state[port];
-}
-
-#ifdef CONFIG_CMD_PD_DEV_DUMP_INFO
-static inline void pd_dev_dump_info(uint16_t dev_id, uint32_t *hash)
-{
- int j;
-
- ccprintf("DevId:%d.%d Hash:", HW_DEV_ID_MAJ(dev_id),
- HW_DEV_ID_MIN(dev_id));
- for (j = 0; j < PD_RW_HASH_SIZE / 4; j++)
- ccprintf(" %08x ", hash[j]);
- ccprintf("\n");
-}
-#endif /* CONFIG_CMD_PD_DEV_DUMP_INFO */
-
-const char *tc_get_current_state(int port)
-{
- if (IS_ENABLED(USB_PD_DEBUG_LABELS))
- return tc_state_names[get_state_tc(port)];
- else
- return "";
-}
-
-uint32_t tc_get_flags(int port)
-{
- return tc[port].flags;
-}
-
-int tc_is_attached_src(int port)
-{
- return IS_ATTACHED_SRC(port);
-}
-
-int tc_is_attached_snk(int port)
-{
- return IS_ATTACHED_SNK(port);
-}
-
-void tc_pd_connection(int port, int en)
-{
- if (en) {
- bool new_pd_capable = false;
-
- if (!TC_CHK_FLAG(port, TC_FLAGS_PARTNER_PD_CAPABLE))
- new_pd_capable = true;
-
- 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)) {
- disable_sleep(SLEEP_MASK_USB_PD);
- }
-
- /*
- * Update the mux state, only when the PD capable flag
- * transitions from 0 to 1. This ensures that PD charger
- * devices, without data capability are not marked as having
- * USB.
- */
- if (new_pd_capable)
- set_usb_mux_with_current_data_role(port);
- } else {
- 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)) {
- int i;
-
- /* If all ports are not connected, allow the sleep */
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- if (pd_capable(i))
- break;
- }
- if (i == board_get_usb_pd_port_count())
- enable_sleep(SLEEP_MASK_USB_PD);
- }
- }
-}
-
-void tc_ctvpd_detected(int port)
-{
- TC_SET_FLAG(port, TC_FLAGS_CTVPD_DETECTED);
-}
-
-void pd_try_vconn_src(int port)
-{
- set_vconn(port, 1);
-}
-
-int tc_check_vconn_swap(int port)
-{
- if (IS_ENABLED(CONFIG_USBC_VCONN)) {
- if (TC_CHK_FLAG(port, TC_FLAGS_REJECT_VCONN_SWAP))
- return 0;
-
- return pd_check_vconn_swap(port);
- } else
- return 0;
-}
-
-void tc_pr_swap_complete(int port, bool success)
-{
- if (IS_ATTACHED_SNK(port)) {
- /*
- * Give the ADCs in the TCPC or PPC time to react following
- * a PS_RDY message received during a SRC to SNK swap.
- * Note: This is empirically determined, not strictly
- * part of the USB PD spec.
- * Note: Swap in progress should not be cleared until the
- * debounce is completed.
- */
- pd_timer_enable(port, TC_TIMER_VBUS_DEBOUNCE, PD_T_DEBOUNCE);
- } else {
- /* PR Swap is no longer in progress */
- TC_CLR_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS);
-
- /*
- * AutoDischargeDisconnect was turned off near the SNK->SRC
- * PR-Swap message. If the swap was a success, Vbus should be
- * valid, so re-enable AutoDischargeDisconnect
- */
- if (success)
- tcpm_enable_auto_discharge_disconnect(port, 1);
- }
-}
-
-void tc_prs_src_snk_assert_rd(int port)
-{
- /*
- * Must be in Attached.SRC or UnorientedDebugAccessory.SRC
- * when this function is called
- */
- if (IS_ATTACHED_SRC(port)) {
- /*
- * Transition to Attached.SNK to
- * DebugAccessory.SNK assert Rd
- */
- TC_SET_FLAG(port, TC_FLAGS_REQUEST_PR_SWAP);
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-void tc_prs_snk_src_assert_rp(int port)
-{
- /*
- * Must be in Attached.SNK or DebugAccessory.SNK
- * when this function is called
- */
- if (IS_ATTACHED_SNK(port)) {
- /*
- * Transition to Attached.SRC or
- * UnorientedDebugAccessory.SRC to assert Rp
- */
- TC_SET_FLAG(port, TC_FLAGS_REQUEST_PR_SWAP);
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-/*
- * Hard Reset is being requested. This should not allow a TC connection
- * to go to an unattached state until the connection is recovered from
- * the hard reset. It is possible for a Hard Reset to cause a timeout
- * in trying to recover and an additional Hard Reset would be issued.
- * During this entire process it is important that the TC is not allowed
- * to go to an unattached state.
- *
- * Type-C Spec Rev 2.0 section 4.5.2.2.5.2
- * Exiting from Attached.SNK State
- * A port that is not a V CONN-Powered USB Device and is not in the
- * process of a USB PD PR_Swap or a USB PD Hard Reset or a USB PD
- * FR_Swap shall transition to Unattached.SNK
- */
-void tc_hard_reset_request(int port)
-{
- TC_SET_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void tc_try_src_override(enum try_src_override_t ov)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_TRY_SRC))
- assert(0);
-
- if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC)) {
- switch (ov) {
- case TRY_SRC_OVERRIDE_OFF: /* 0 */
- pd_try_src_override = TRY_SRC_OVERRIDE_OFF;
- break;
- case TRY_SRC_OVERRIDE_ON: /* 1 */
- pd_try_src_override = TRY_SRC_OVERRIDE_ON;
- break;
- default:
- pd_try_src_override = TRY_SRC_NO_OVERRIDE;
- }
- }
-}
-
-enum try_src_override_t tc_get_try_src_override(void)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_TRY_SRC))
- assert(0);
-
- return pd_try_src_override;
-}
-
-void tc_snk_power_off(int port)
-{
- if (IS_ATTACHED_SNK(port)) {
- TC_SET_FLAG(port, TC_FLAGS_POWER_OFF_SNK);
- sink_stop_drawing_current(port);
- }
-}
-
-int tc_src_power_on(int port)
-{
- /*
- * Check our OC event counter. If we've exceeded our threshold, then
- * let's latch our source path off to prevent continuous cycling. When
- * the PD state machine detects a disconnection on the CC lines, we will
- * reset our OC event counter.
- */
- if (IS_ENABLED(CONFIG_USBC_OCP) && usbc_ocp_is_port_latched_off(port))
- return EC_ERROR_ACCESS_DENIED;
-
- if (IS_ATTACHED_SRC(port))
- return pd_set_power_supply_ready(port);
-
- return 0;
-}
-
-void tc_src_power_off(int port)
-{
- /* Remove VBUS */
- pd_power_supply_reset(port);
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER))
- charge_manager_set_ceil(port, CEIL_REQUESTOR_PD,
- CHARGE_CEIL_NONE);
-}
-
-/* Set what role the partner is right now, for the PPC and OCP module */
-static void tc_set_partner_role(int port, enum ppc_device_role role)
-{
- if (IS_ENABLED(CONFIG_USBC_PPC))
- ppc_dev_is_connected(port, role);
-
- if (IS_ENABLED(CONFIG_USBC_OCP)) {
- usbc_ocp_snk_is_connected(port, role == PPC_DEV_SNK);
- /*
- * Clear the overcurrent event counter
- * since we've detected a disconnect.
- */
- if (role == PPC_DEV_DISCONNECTED)
- usbc_ocp_clear_event_counter(port);
- }
-}
-
-/*
- * Depending on the load on the processor and the tasks running
- * it can take a while for the task associated with this port
- * to run. So build in 1ms delays, for up to 300ms, to wait for
- * the suspend to actually happen.
- */
-#define SUSPEND_SLEEP_DELAY 1
-#define SUSPEND_SLEEP_RETRIES 300
-
-void pd_set_suspend(int port, int suspend)
-{
- if (pd_is_port_enabled(port) == !suspend)
- return;
-
- /* Track if we are suspended or not */
- if (suspend) {
- int wait = 0;
-
- TC_SET_FLAG(port, TC_FLAGS_REQUEST_SUSPEND);
-
- /*
- * Avoid deadlock when running from task
- * which we are going to suspend
- */
- if (PD_PORT_TO_TASK_ID(port) == task_get_current())
- return;
-
- task_wake(PD_PORT_TO_TASK_ID(port));
-
- /* Sleep this task if we are not suspended */
- while (pd_is_port_enabled(port)) {
- if (++wait > SUSPEND_SLEEP_RETRIES) {
- CPRINTS("C%d: NOT SUSPENDED after %dms",
- port, wait * SUSPEND_SLEEP_DELAY);
- return;
- }
- msleep(SUSPEND_SLEEP_DELAY);
- }
- } else {
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_SUSPEND);
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-void pd_set_error_recovery(int port)
-{
- TC_SET_FLAG(port, TC_FLAGS_REQUEST_ERROR_RECOVERY);
-}
-
-int pd_is_port_enabled(int port)
-{
- /*
- * Checking get_state_tc(port) from another task isn't safe since it
- * can return TC_DISABLED before tc_cc_open_entry and tc_disabled_entry
- * are complete. So check TC_FLAGS_SUSPENDED instead.
- */
- return !TC_CHK_FLAG(port, TC_FLAGS_SUSPENDED);
-}
-
-int pd_fetch_acc_log_entry(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PE_SM))
- pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_GET_LOG, NULL, 0);
-
- return EC_RES_SUCCESS;
-}
-
-enum tcpc_cc_polarity pd_get_polarity(int port)
-{
- return tc[port].polarity;
-}
-
-enum pd_data_role pd_get_data_role(int port)
-{
- return tc[port].data_role;
-}
-
-enum pd_power_role pd_get_power_role(int port)
-{
- return tc[port].power_role;
-}
-
-enum pd_cc_states pd_get_task_cc_state(int port)
-{
- return tc[port].cc_state;
-}
-
-uint8_t pd_get_task_state(int port)
-{
- return get_state_tc(port);
-}
-
-bool pd_get_vconn_state(int port)
-{
- return !!TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON);
-}
-
-const char *pd_get_task_state_name(int port)
-{
- return tc_get_current_state(port);
-}
-
-void pd_vbus_low(int port)
-{
- TC_CLR_FLAG(port, TC_FLAGS_VBUS_NEVER_LOW);
-}
-
-int pd_is_connected(int port)
-{
- return (IS_ATTACHED_SRC(port) ||
- (IS_ENABLED(CONFIG_USB_PE_SM) &&
- ((get_state_tc(port) == TC_CT_UNATTACHED_SNK) ||
- (get_state_tc(port) == TC_CT_ATTACHED_SNK))) ||
- IS_ATTACHED_SNK(port));
-}
-
-bool pd_is_disconnected(int port)
-{
- return !pd_is_connected(port);
-}
-
-/*
- * PD functions which query our fixed PDO flags. Both the source and sink
- * capabilities can present these values, and they should match between the two
- * for compliant partners.
- */
-static bool pd_check_fixed_flag(int port, uint32_t flag)
-{
- uint32_t fixed_pdo;
-
- if (pd_get_src_cap_cnt(port) != 0)
- fixed_pdo = *pd_get_src_caps(port);
- else if (pd_get_snk_cap_cnt(port) != 0)
- fixed_pdo = *pd_get_snk_caps(port);
- else
- return false;
-
- /*
- * Error check that first PDO is fixed, as 6.4.1 Capabilities requires
- * in the Power Delivery Specification.
- * "The vSafe5V Fixed Supply Object Shall always be the first object"
- */
- if ((fixed_pdo & PDO_TYPE_MASK) != PDO_TYPE_FIXED)
- return false;
-
- return fixed_pdo & flag;
-}
-
-bool pd_get_partner_data_swap_capable(int port)
-{
- return pd_check_fixed_flag(port, PDO_FIXED_DATA_SWAP);
-}
-
-bool pd_get_partner_usb_comm_capable(int port)
-{
- return pd_check_fixed_flag(port, PDO_FIXED_COMM_CAP);
-}
-
-bool pd_get_partner_dual_role_power(int port)
-{
- return pd_check_fixed_flag(port, PDO_FIXED_DUAL_ROLE);
-}
-
-bool pd_get_partner_unconstr_power(int port)
-{
- return pd_check_fixed_flag(port, PDO_FIXED_UNCONSTRAINED);
-}
-
-static void bc12_role_change_handler(int port, enum pd_data_role prev_data_role,
- enum pd_data_role data_role)
-{
- int event = 0;
- int task_id = USB_CHG_PORT_TO_TASK_ID(port);
- bool role_changed = (data_role != prev_data_role);
-
- if (!IS_ENABLED(CONFIG_BC12_DETECT_DATA_ROLE_TRIGGER))
- return;
-
- /* Get the data role of our device */
- switch (data_role) {
- case PD_ROLE_UFP:
- /* Only trigger BC12 detection on a role change */
- if (role_changed)
- event = USB_CHG_EVENT_DR_UFP;
- break;
- case PD_ROLE_DFP:
- /* Only trigger BC12 host mode on a role change */
- if (role_changed)
- event = USB_CHG_EVENT_DR_DFP;
- break;
- case PD_ROLE_DISCONNECTED:
- event = USB_CHG_EVENT_CC_OPEN;
- break;
- default:
- return;
- }
-
- if (event)
- task_set_event(task_id, event);
-}
-
-/*
- * TCPC CC/Rp management
- */
-static void typec_select_pull(int port, enum tcpc_cc_pull pull)
-{
- tc[port].select_cc_pull = pull;
-}
-void typec_select_src_current_limit_rp(int port, enum tcpc_rp_value rp)
-{
- tc[port].select_current_limit_rp = rp;
- if (IS_ATTACHED_SRC(port))
- TC_SET_FLAG(port, TC_FLAGS_UPDATE_CURRENT);
-}
-__overridable int typec_get_default_current_limit_rp(int port)
-{
- return CONFIG_USB_PD_PULLUP;
-}
-void typec_select_src_collision_rp(int port, enum tcpc_rp_value rp)
-{
- tc[port].select_collision_rp = rp;
-}
-static enum tcpc_rp_value typec_get_active_select_rp(int port)
-{
- /* Explicit contract will use the collision Rp */
- if (IS_ENABLED(CONFIG_USB_PD_REV30) &&
- pe_is_explicit_contract(port))
- return tc[port].select_collision_rp;
- return tc[port].select_current_limit_rp;
-}
-int typec_update_cc(int port)
-{
- int rv;
- enum tcpc_cc_pull pull = tc[port].select_cc_pull;
- enum tcpc_rp_value rp = typec_get_active_select_rp(port);
-
- rv = tcpm_select_rp_value(port, rp);
- if (rv)
- return rv;
-
- return tcpm_set_cc(port, pull);
-}
-
-#ifdef CONFIG_USB_PE_SM
-/*
- * This function performs a source hard reset. It should be called
- * repeatedly until a true value is returned, signaling that the
- * source hard reset is complete. A false value is returned otherwise.
- */
-static bool tc_perform_src_hard_reset(int port)
-{
- switch (tc[port].ps_reset_state) {
- case PS_STATE0:
- /* Remove VBUS */
- tc_src_power_off(port);
-
- /* Turn off VCONN */
- set_vconn(port, 0);
-
- /* Set role to DFP */
- tc_set_data_role(port, PD_ROLE_DFP);
-
- tc[port].ps_reset_state = PS_STATE1;
- pd_timer_enable(port, TC_TIMER_TIMEOUT, PD_T_SRC_RECOVER);
- return false;
- case PS_STATE1:
- /* Enable VBUS */
- tc_src_power_on(port);
-
- /* Update the Rp Value */
- typec_update_cc(port);
-
- /* Turn off VCONN */
- set_vconn(port, 1);
-
- tc[port].ps_reset_state = PS_STATE2;
- pd_timer_enable(port, TC_TIMER_TIMEOUT,
- PD_POWER_SUPPLY_TURN_ON_DELAY);
- return false;
- case PS_STATE2:
- /* Tell Policy Engine Hard Reset is complete */
- pe_ps_reset_complete(port);
-
- tc[port].ps_reset_state = PS_STATE0;
- return true;
- }
-
- /*
- * This return is added to appease the compiler. It should
- * never be reached because the switch handles all possible
- * cases of the enum ps_reset_sequence type.
- */
- return true;
-}
-
-/*
- * Wait for recovery after a hard reset. Call repeatedly until true is
- * returned, signaling that the hard reset is complete.
- */
-static bool tc_perform_snk_hard_reset(int port)
-{
- switch (tc[port].ps_reset_state) {
- case PS_STATE0:
- /* Hard reset sets us back to default data role */
- tc_set_data_role(port, PD_ROLE_UFP);
-
- /*
- * When VCONN is supported, the Hard Reset Shall cause
- * the Port with the Rd resistor asserted to turn off
- * VCONN.
- */
- if (IS_ENABLED(CONFIG_USBC_VCONN) &&
- TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON))
- set_vconn(port, 0);
-
- /* Wait up to tVSafe0V for Vbus to disappear */
- tc[port].ps_reset_state = PS_STATE1;
- pd_timer_enable(port, TC_TIMER_TIMEOUT, PD_T_SAFE_0V);
- return false;
- case PS_STATE1:
- if (pd_check_vbus_level(port, VBUS_SAFE0V)) {
- /*
- * Partner dropped Vbus, reduce our current consumption
- * and await its return.
- */
- sink_stop_drawing_current(port);
-
- tcpm_enable_auto_discharge_disconnect(port, 0);
-
- /* Move on to waiting for the return of Vbus */
- tc[port].ps_reset_state = PS_STATE2;
- pd_timer_enable(port, TC_TIMER_TIMEOUT,
- PD_T_SRC_RECOVER_MAX +
- PD_T_SRC_TURN_ON);
- }
-
- if (pd_timer_is_expired(port, TC_TIMER_TIMEOUT)) {
- /*
- * No Vbus drop likely indicates a non-PD port partner,
- * move to the next stage anyway.
- */
- tc[port].ps_reset_state = PS_STATE2;
- pd_timer_enable(port, TC_TIMER_TIMEOUT,
- PD_T_SRC_RECOVER_MAX +
- PD_T_SRC_TURN_ON);
- }
- return false;
- case PS_STATE2:
- /*
- * Look for the voltage to be above disconnect. Since we didn't
- * drop our draw on non-PD partners, they may have dipped below
- * vSafe5V but still be in a valid connected voltage.
- */
- if (!pd_check_vbus_level(port, VBUS_REMOVED)) {
- /*
- * Inform policy engine that power supply
- * reset is complete
- */
- tc[port].ps_reset_state = PS_STATE0;
- pe_ps_reset_complete(port);
-
- /*
- * Now that VBUS is back, let's notify charge manager
- * regarding the source's current capabilities.
- * sink_power_sub_states() reacts to changes in CC
- * terminations, however during a HardReset, the
- * terminations of a non-PD port partner will not
- * change. Therefore, set the debounce time to right
- * now, such that we'll actually reset the correct input
- * current limit.
- */
- pd_timer_enable(port, TC_TIMER_CC_DEBOUNCE, 0);
- sink_power_sub_states(port);
-
- /* Power is back, Enable AutoDischargeDisconnect */
- tcpm_enable_auto_discharge_disconnect(port, 1);
- return true;
- }
- /*
- * If Vbus isn't back after wait + tSrcTurnOn, go unattached
- */
- if (pd_timer_is_expired(port, TC_TIMER_TIMEOUT)) {
- tc[port].ps_reset_state = PS_STATE0;
- set_state_tc(port, TC_UNATTACHED_SNK);
- return true;
- }
- }
-
- return false;
-}
-#endif /* CONFIG_USB_PE_SM */
-
-void tc_start_error_recovery(int port)
-{
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- /*
- * The port should transition to the ErrorRecovery state
- * from any other state when directed.
- */
- set_state_tc(port, TC_ERROR_RECOVERY);
-}
-
-static void restart_tc_sm(int port, enum usb_tc_state start_state)
-{
- int res;
-
- /* Clear flags before we transitions states */
- tc[port].flags = 0;
-
- res = tcpm_init(port);
-
- CPRINTS("C%d: TCPC init %s", port, res ? "failed" : "ready");
-
- /*
- * Update the Rp Value. We don't need to update CC lines though as that
- * happens in below set_state transition.
- */
- typec_select_src_current_limit_rp(port,
- typec_get_default_current_limit_rp(port));
-
- /* Disable if restart failed, otherwise start in default state. */
- set_state_tc(port, res ? TC_DISABLED : start_state);
-
- if (IS_ENABLED(CONFIG_USBC_SS_MUX))
- /* Initialize USB mux to its default state */
- usb_mux_init(port);
-
- if (IS_ENABLED(CONFIG_USBC_PPC)) {
- /*
- * Wait to initialize the PPC after tcpc, which sets
- * the correct Rd values; otherwise the TCPC might
- * not be pulling the CC lines down when the PPC connects the
- * CC lines from the USB connector to the TCPC cause the source
- * to drop Vbus causing a brown out.
- */
- ppc_init(port);
- }
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) {
- /*
- * Only initialize PD supplier current limit to 0.
- * Defer initializing type-C supplier current limit
- * to Unattached.SNK or Attached.SNK.
- */
- pd_set_input_current_limit(port, 0, 0);
- charge_manager_update_dualrole(port, CAP_UNKNOWN);
- }
-
- /*
- * PD r3.0 v2.0, ss6.2.1.1.5:
- * After a physical or logical (USB Type-C Error Recovery) Attach, a
- * Port discovers the common Specification Revision level between itself
- * and its Port Partner and/or the Cable Plug(s), and uses this
- * Specification Revision level until a Detach, Hard Reset or Error
- * Recovery happens.
- *
- * This covers the Error Recovery case, because TC_ERROR_RECOVERY
- * reinitializes the TC state machine. This also covers the implicit
- * case when PD is suspended and resumed or when the state machine is
- * first initialized.
- */
- if (IS_ENABLED(CONFIG_USB_PRL_SM))
- prl_set_default_pd_revision(port);
-
-#ifdef CONFIG_USB_PE_SM
- tc_enable_pd(port, 0);
- tc[port].ps_reset_state = PS_STATE0;
-#endif
-}
-
-void tc_state_init(int port)
-{
- enum usb_tc_state first_state;
-
- /* For test builds, replicate static initialization */
- if (IS_ENABLED(TEST_BUILD)) {
- int i;
-
- for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; ++i) {
- memset(&tc[i], 0, sizeof(tc[i]));
- drp_state[i] = CONFIG_USB_PD_INITIAL_DRP_STATE;
- }
- }
-
- /* If port is not available, there is nothing to initialize */
- if (port >= board_get_usb_pd_port_count()) {
- tc_enable_pd(port, 0);
- TC_SET_FLAG(port, TC_FLAGS_REQUEST_SUSPEND);
- return;
- }
-
-
- /* Allow system to set try src enable */
- if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC))
- tc_try_src_override(TRY_SRC_NO_OVERRIDE);
-
- /*
- * Set initial PD communication policy.
- */
- tc_policy_pd_enable(port, pd_comm_allowed_by_policy());
-
-#ifdef HAS_TASK_CHIPSET
- /* Set dual-role state based on chipset power state */
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
- pd_set_dual_role_and_event(port, PD_DRP_FORCE_SINK, 0);
- else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND))
- pd_set_dual_role_and_event(port, pd_get_drp_state_in_suspend(), 0);
- else /* CHIPSET_STATE_ON */
- pd_set_dual_role_and_event(port, PD_DRP_TOGGLE_ON, 0);
-#else
- pd_set_dual_role_and_event(port, board_tc_get_initial_drp_mode(port), 0);
-#endif
-
- /*
- * We are going to apply CC open (start with ErrorRecovery state)
- * unless there is something which forbids us to do that (one of
- * conditions below is true)
- */
- first_state = TC_ERROR_RECOVERY;
-
- /*
- * If we just lost power, don't apply CC open. Otherwise we would boot
- * loop, and if this is a fresh power on, then we know there isn't any
- * stale PD state as well.
- */
- if (system_get_reset_flags() &
- (EC_RESET_FLAG_BROWNOUT | EC_RESET_FLAG_POWER_ON)) {
- first_state = TC_UNATTACHED_SNK;
- }
-
- /*
- * If this is non-EFS2 device, battery is not present and EC RO doesn't
- * keep power-on reset flag after reset caused by H1, then don't apply
- * CC open because it will cause brown out.
- *
- * Please note that we are checking if CONFIG_BOARD_RESET_AFTER_POWER_ON
- * is defined now, but actually we need to know if it was enabled in
- * EC RO! It was assumed that if CONFIG_BOARD_RESET_AFTER_POWER_ON is
- * defined now it was defined in EC RO too.
- */
- if (!IS_ENABLED(CONFIG_BOARD_RESET_AFTER_POWER_ON) &&
- !IS_ENABLED(CONFIG_VBOOT_EFS2) && IS_ENABLED(CONFIG_BATTERY) &&
- (battery_is_present() == BP_NO)) {
- first_state = TC_UNATTACHED_SNK;
- }
-
- if (first_state == TC_UNATTACHED_SNK) {
- /* Turn off any previous sourcing */
- tc_src_power_off(port);
- set_vconn(port, 0);
- }
-
-#ifdef CONFIG_USB_PD_TCPC_BOARD_INIT
- /* Board specific TCPC init */
- board_tcpc_init();
-#endif
-
- /*
- * Start with ErrorRecovery state if we can to put us in
- * a clean state from any previous boots.
- */
- restart_tc_sm(port, first_state);
-}
-
-enum pd_cable_plug tc_get_cable_plug(int port)
-{
- /*
- * Messages sent by this state machine are always from a DFP/UFP,
- * i.e. the chromebook.
- */
- return PD_PLUG_FROM_DFP_UFP;
-}
-
-void pd_comm_enable(int port, int en)
-{
- tc_policy_pd_enable(port, en);
-}
-
-uint8_t tc_get_polarity(int port)
-{
- return tc[port].polarity;
-}
-
-uint8_t tc_get_pd_enabled(int port)
-{
- return !tc[port].pd_disabled_mask;
-}
-
-bool pd_alt_mode_capable(int port)
-{
- return IS_ENABLED(CONFIG_USB_PE_SM) && tc_get_pd_enabled(port);
-}
-
-void tc_set_power_role(int port, enum pd_power_role role)
-{
- tc[port].power_role = role;
-}
-
-/*
- * Private Functions
- */
-
-/* Set GPIO_CCD_MODE_ODL gpio */
-static void set_ccd_mode(const int port, const bool enable)
-{
- if (IS_ENABLED(CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT) &&
- port == CONFIG_CCD_USBC_PORT_NUMBER) {
- if (enable)
- CPRINTS("Asserting GPIO_CCD_MODE_ODL");
- gpio_set_level(_GPIO_CCD_MODE_ODL, !enable);
- }
-}
-
-/* Set the TypeC state machine to a new state. */
-static void set_state_tc(const int port, const enum usb_tc_state new_state)
-{
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- set_state(port, &tc[port].ctx, &tc_states[new_state]);
-}
-
-/* Get the current TypeC state. */
-test_export_static enum usb_tc_state get_state_tc(const int port)
-{
- /* Default to returning TC_STATE_COUNT if no state has been set */
- if (tc[port].ctx.current == NULL)
- return TC_STATE_COUNT;
- else
- return tc[port].ctx.current - &tc_states[0];
-}
-
-/* Get the previous TypeC state. */
-static enum usb_tc_state get_last_state_tc(const int port)
-{
- return tc[port].ctx.previous - &tc_states[0];
-}
-
-static void print_current_state(const int port)
-{
- if (IS_ENABLED(USB_PD_DEBUG_LABELS))
- CPRINTS_L1("C%d: %s", port, tc_state_names[get_state_tc(port)]);
- else
- CPRINTS("C%d: tc-st%d", port, get_state_tc(port));
-}
-
-static void handle_device_access(int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER) &&
- get_state_tc(port) == TC_LOW_POWER_MODE) {
- tc_start_event_loop(port);
- pd_timer_enable(port, TC_TIMER_LOW_POWER_TIME,
- PD_LPM_DEBOUNCE_US);
- }
-}
-
-void tc_event_check(int port, int evt)
-{
-#ifdef DEBUG_PRINT_FLAG_AND_EVENT_NAMES
- if (evt != TASK_EVENT_TIMER)
- print_bits(port, "Event", evt, event_bit_names,
- ARRAY_SIZE(event_bit_names));
-#endif
-
- if (evt & PD_EXIT_LOW_POWER_EVENT_MASK)
- TC_SET_FLAG(port, TC_FLAGS_CHECK_CONNECTION);
-
- if (evt & PD_EVENT_DEVICE_ACCESSED)
- handle_device_access(port);
-
- if (evt & PD_EVENT_TCPC_RESET)
- reset_device_and_notify(port);
-
- if (evt & PD_EVENT_RX_HARD_RESET)
- pd_execute_hard_reset(port);
-
- if (evt & PD_EVENT_SEND_HARD_RESET) {
- /* Pass Hard Reset request to PE layer if available */
- if (IS_ENABLED(CONFIG_USB_PE_SM) && tc_get_pd_enabled(port))
- pd_dpm_request(port, DPM_REQUEST_HARD_RESET_SEND);
- }
-
-#ifdef CONFIG_POWER_COMMON
- if (IS_ENABLED(CONFIG_POWER_COMMON)) {
- if (evt & PD_EVENT_POWER_STATE_CHANGE)
- handle_new_power_state(port);
- }
-#endif /* CONFIG_POWER_COMMON */
-
- if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
- int i;
-
- /*
- * Notify all ports of sysjump
- */
- if (evt & PD_EVENT_SYSJUMP) {
- for (i = 0; i <
- CONFIG_USB_PD_PORT_MAX_COUNT; i++)
- dpm_set_mode_exit_request(i);
- notify_sysjump_ready();
- }
- }
-
- if (evt & PD_EVENT_UPDATE_DUAL_ROLE)
- pd_update_dual_role_config(port);
-}
-
-/*
- * CC values for regular sources and Debug sources (aka DTS)
- *
- * Source type Mode of Operation CC1 CC2
- * ---------------------------------------------
- * Regular Default USB Power RpUSB Open
- * Regular USB-C @ 1.5 A Rp1A5 Open
- * Regular USB-C @ 3 A Rp3A0 Open
- * DTS Default USB Power Rp3A0 Rp1A5
- * DTS USB-C @ 1.5 A Rp1A5 RpUSB
- * DTS USB-C @ 3 A Rp3A0 RpUSB
- */
-
-void tc_set_data_role(int port, enum pd_data_role role)
-{
- enum pd_data_role prev_data_role;
-
- prev_data_role = tc[port].data_role;
- tc[port].data_role = role;
-
- if (IS_ENABLED(CONFIG_USBC_SS_MUX))
- set_usb_mux_with_current_data_role(port);
-
- /*
- * Run any board-specific code for role swap (e.g. setting OTG signals
- * to SoC).
- */
- pd_execute_data_swap(port, role);
-
- /*
- * For BC1.2 detection that is triggered on data role change events
- * instead of VBUS changes, need to set an event to wake up the USB_CHG
- * task and indicate the current data role.
- */
- bc12_role_change_handler(port, prev_data_role, tc[port].data_role);
-
- /* Notify TCPC of role update */
- tcpm_set_msg_header(port, tc[port].power_role, tc[port].data_role);
-}
-
-static void sink_stop_drawing_current(int port)
-{
- pd_set_input_current_limit(port, 0, 0);
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) {
- typec_set_input_current_limit(port, 0, 0);
- charge_manager_set_ceil(port,
- CEIL_REQUESTOR_PD, CHARGE_CEIL_NONE);
- }
-}
-
-static void pd_update_try_source(void)
-{
-#ifdef CONFIG_USB_PD_TRY_SRC
- tc_enable_try_src(pd_is_try_source_capable());
-#endif
-}
-DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, pd_update_try_source, HOOK_PRIO_DEFAULT);
-
-static void set_vconn(int port, int enable)
-{
- if (enable)
- TC_SET_FLAG(port, TC_FLAGS_VCONN_ON);
- else
- TC_CLR_FLAG(port, TC_FLAGS_VCONN_ON);
-
- /*
- * Check our OC event counter. If we've exceeded our threshold, then
- * let's latch our source path off to prevent continuous cycling. When
- * the PD state machine detects a disconnection on the CC lines, we will
- * reset our OC event counter.
- */
- if (IS_ENABLED(CONFIG_USBC_OCP) &&
- enable && usbc_ocp_is_port_latched_off(port))
- return;
-
- /*
- * Disable PPC Vconn first then TCPC in case the voltage feeds back
- * to TCPC and damages.
- */
- if (IS_ENABLED(CONFIG_USBC_PPC_VCONN) && !enable)
- ppc_set_vconn(port, 0);
-
- /*
- * Some TCPCs/PPC combinations can trigger OVP if the TCPC doesn't
- * source VCONN. This happens if the TCPC will trip OVP with 5V, and the
- * PPC doesn't isolate the TCPC from VCONN when sourcing. But, some PPCs
- * which do isolate the TCPC can't handle 5V on its host-side CC pins,
- * so the TCPC shouldn't source VCONN in those cases.
- *
- * In the first case, both TCPC and PPC will potentially source Vconn,
- * but that should be okay since Vconn has "make before break"
- * electrical requirements when swapping anyway.
- *
- * See b/72961003 and b/180973460
- */
- tcpm_set_vconn(port, enable);
-
- if (IS_ENABLED(CONFIG_USBC_PPC_VCONN) && enable)
- ppc_set_vconn(port, 1);
-}
-
-/* This must only be called from the PD task */
-static void pd_update_dual_role_config(int port)
-{
- if (tc[port].power_role == PD_ROLE_SOURCE &&
- (drp_state[port] == PD_DRP_FORCE_SINK ||
- (drp_state[port] == PD_DRP_TOGGLE_OFF &&
- get_state_tc(port) == TC_UNATTACHED_SRC))) {
- /*
- * Change to sink if port is currently a source AND (new DRP
- * state is force sink OR new DRP state is toggle off and we are
- * in the source disconnected state).
- */
- set_state_tc(port, TC_UNATTACHED_SNK);
- } else if (tc[port].power_role == PD_ROLE_SINK &&
- drp_state[port] == PD_DRP_FORCE_SOURCE) {
- /*
- * Change to source if port is currently a sink and the
- * new DRP state is force source.
- */
- set_state_tc(port, TC_UNATTACHED_SRC);
- }
-}
-
-__maybe_unused static void handle_new_power_state(int port)
-{
- if (!IS_ENABLED(CONFIG_POWER_COMMON))
- assert(0);
-
- if (IS_ENABLED(CONFIG_POWER_COMMON) &&
- IS_ENABLED(CONFIG_USB_PE_SM)) {
- if (chipset_in_or_transitioning_to_state(
- CHIPSET_STATE_ANY_OFF)) {
- /*
- * The SoC will negotiate alternate mode again when it
- * boots up
- */
- dpm_set_mode_exit_request(port);
- }
- }
-
- /*
- * If the sink port was sourcing Vconn, and can no longer, request a
- * hard reset on this port to restore Vconn to the source.
- */
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- if (tc_is_vconn_src(port) && tc_is_attached_snk(port) &&
- !pd_check_vconn_swap(port))
- pd_dpm_request(port, DPM_REQUEST_HARD_RESET_SEND);
- }
-
- /*
- * TC_FLAGS_UPDATE_USB_MUX is set on chipset startup and shutdown.
- * Set the USB mux according to the new power state. If the chipset
- * is transitioning to OFF, this disconnects USB and DP mux.
- *
- * Transitions to and from suspend states do not change the USB mux
- * or the alternate mode configuration.
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_UPDATE_USB_MUX)) {
- TC_CLR_FLAG(port, TC_FLAGS_UPDATE_USB_MUX);
- set_usb_mux_with_current_data_role(port);
- }
-}
-
-#ifdef CONFIG_USBC_VCONN_SWAP
-void pd_request_vconn_swap_off(int port)
-{
- if (get_state_tc(port) == TC_ATTACHED_SRC ||
- get_state_tc(port) == TC_ATTACHED_SNK) {
- TC_SET_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_OFF);
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-void pd_request_vconn_swap_on(int port)
-{
- if (get_state_tc(port) == TC_ATTACHED_SRC ||
- get_state_tc(port) == TC_ATTACHED_SNK) {
- TC_SET_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_ON);
- task_wake(PD_PORT_TO_TASK_ID(port));
- }
-}
-
-void pd_request_vconn_swap(int port)
-{
- pd_dpm_request(port, DPM_REQUEST_VCONN_SWAP);
-}
-#endif
-
-int tc_is_vconn_src(int port)
-{
- if (IS_ENABLED(CONFIG_USBC_VCONN))
- return TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON);
- else
- return 0;
-}
-
-static __maybe_unused int reset_device_and_notify(int port)
-{
- int rv;
- int task, waiting_tasks;
-
- /* This should only be called from the PD task */
- assert(port == TASK_ID_TO_PD_PORT(task_get_current()));
-
- TC_SET_FLAG(port, TC_FLAGS_LPM_TRANSITION);
- rv = tcpm_init(port);
- TC_CLR_FLAG(port, TC_FLAGS_LPM_TRANSITION);
- TC_CLR_FLAG(port, TC_FLAGS_LPM_ENGAGED);
- tc_start_event_loop(port);
-
- CPRINTS("C%d: TCPC init %s", port, rv ? "failed!" : "ready");
-
- /*
- * Before getting the other tasks that are waiting, clear the reset
- * event from this PD task to prevent multiple reset/init events
- * occurring.
- *
- * The double reset event happens when the higher priority PD interrupt
- * task gets an interrupt during the above tcpm_init function. When that
- * occurs, the higher priority task waits correctly for us to finish
- * waking the TCPC, but it has also set PD_EVENT_TCPC_RESET again, which
- * would result in a second, unnecessary init.
- */
- atomic_clear_bits(task_get_event_bitmap(task_get_current()),
- PD_EVENT_TCPC_RESET);
-
- waiting_tasks = atomic_clear(&tc[port].tasks_waiting_on_reset);
-
- /* Wake up all waiting tasks. */
- while (waiting_tasks) {
- task = __fls(waiting_tasks);
- waiting_tasks &= ~BIT(task);
- task_set_event(task, TASK_EVENT_PD_AWAKE);
- }
-
- return rv;
-}
-
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
-void pd_wait_exit_low_power(int port)
-{
- if (!TC_CHK_FLAG(port, TC_FLAGS_LPM_ENGAGED))
- return;
-
- if (port == TASK_ID_TO_PD_PORT(task_get_current())) {
- if (!TC_CHK_FLAG(port, TC_FLAGS_LPM_TRANSITION))
- reset_device_and_notify(port);
- } else {
- /* Otherwise, we need to wait for the TCPC reset to complete */
- atomic_or(&tc[port].tasks_waiting_on_reset,
- 1 << task_get_current());
- /*
- * NOTE: We could be sending the PD task the reset event while
- * it is already processing the reset event. If that occurs,
- * then we will reset the TCPC multiple times, which is
- * undesirable but most likely benign. Empirically, this doesn't
- * happen much, but it if starts occurring, we can add a guard
- * to prevent/reduce it.
- */
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_TCPC_RESET);
- task_wait_event_mask(TASK_EVENT_PD_AWAKE, -1);
- }
-}
-
-/*
- * This can be called from any task. If we are in the PD task, we can handle
- * immediately. Otherwise, we need to notify the PD task via event.
- */
-void pd_device_accessed(int port)
-{
- if (port == TASK_ID_TO_PD_PORT(task_get_current()))
- handle_device_access(port);
- else
- task_set_event(PD_PORT_TO_TASK_ID(port),
- PD_EVENT_DEVICE_ACCESSED);
-}
-
-/*
- * TODO(b/137493121): Move this function to a separate file that's shared
- * between the this and the original stack.
- */
-void pd_prevent_low_power_mode(int port, int prevent)
-{
- const int current_task_mask = (1 << task_get_current());
-
- if (prevent)
- atomic_or(&tc[port].tasks_preventing_lpm, current_task_mask);
- else
- atomic_clear_bits(&tc[port].tasks_preventing_lpm,
- current_task_mask);
-}
-#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */
-
-static void sink_power_sub_states(int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2, cc;
- enum tcpc_cc_voltage_status new_cc_voltage;
-
- tcpm_get_cc(port, &cc1, &cc2);
-
- cc = polarity_rm_dts(tc[port].polarity) ? cc2 : cc1;
-
- if (cc == TYPEC_CC_VOLT_RP_DEF)
- new_cc_voltage = TYPEC_CC_VOLT_RP_DEF;
- else if (cc == TYPEC_CC_VOLT_RP_1_5)
- new_cc_voltage = TYPEC_CC_VOLT_RP_1_5;
- else if (cc == TYPEC_CC_VOLT_RP_3_0)
- new_cc_voltage = TYPEC_CC_VOLT_RP_3_0;
- else
- new_cc_voltage = TYPEC_CC_VOLT_OPEN;
-
- /* Debounce the cc state */
- if (new_cc_voltage != tc[port].cc_voltage) {
- tc[port].cc_voltage = new_cc_voltage;
- pd_timer_enable(port, TC_TIMER_CC_DEBOUNCE,
- PD_T_RP_VALUE_CHANGE);
- return;
- }
-
- if (!pd_timer_is_disabled(port, TC_TIMER_CC_DEBOUNCE)) {
- if (!pd_timer_is_expired(port, TC_TIMER_CC_DEBOUNCE))
- return;
-
- pd_timer_disable(port, TC_TIMER_CC_DEBOUNCE);
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) {
- tc[port].typec_curr = usb_get_typec_current_limit(
- tc[port].polarity, cc1, cc2);
-
- typec_set_input_current_limit(port,
- tc[port].typec_curr, TYPE_C_VOLTAGE);
- charge_manager_update_dualrole(port, CAP_DEDICATED);
- }
- }
-}
-
-
-/*
- * TYPE-C State Implementations
- */
-
-/**
- * Disabled
- *
- * Super State Entry Actions:
- * Remove the terminations from CC
- * Set VBUS and VCONN off
- */
-static void tc_disabled_entry(const int port)
-{
- print_current_state(port);
- /*
- * We have completed tc_cc_open_entry (our super state), so set flag
- * to indicate to pd_is_port_enabled that we are now suspended.
- */
- TC_SET_FLAG(port, TC_FLAGS_SUSPENDED);
-}
-
-static void tc_disabled_run(const int port)
-{
- /* If pd_set_suspend clears the request, go to TC_UNATTACHED_SNK/SRC. */
- if (!TC_CHK_FLAG(port, TC_FLAGS_REQUEST_SUSPEND)) {
- set_state_tc(port, drp_state[port] == PD_DRP_FORCE_SOURCE ?
- TC_UNATTACHED_SRC : TC_UNATTACHED_SNK);
- } else {
- if (IS_ENABLED(CONFIG_USBC_RETIMER_FW_UPDATE)) {
- if (TC_CHK_FLAG(port,
- TC_FLAGS_USB_RETIMER_FW_UPDATE_LTD_RUN)) {
- TC_CLR_FLAG(port,
- TC_FLAGS_USB_RETIMER_FW_UPDATE_LTD_RUN);
- usb_retimer_fw_update_process_op_cb(port);
- }
- }
- tc_pause_event_loop(port);
- }
-}
-
-static void tc_disabled_exit(const int port)
-{
- int rv;
-
- tc_start_event_loop(port);
- TC_CLR_FLAG(port, TC_FLAGS_SUSPENDED);
-
- rv = tcpm_init(port);
- CPRINTS("C%d: TCPC init %s", port, rv ? "failed!" : "ready");
-}
-
-/**
- * ErrorRecovery
- *
- * Super State Entry Actions:
- * Remove the terminations from CC
- * Set's VBUS and VCONN off
- */
-static void tc_error_recovery_entry(const int port)
-{
- print_current_state(port);
-
- pd_timer_enable(port, TC_TIMER_TIMEOUT, PD_T_ERROR_RECOVERY);
-
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_ERROR_RECOVERY);
-}
-
-static void tc_error_recovery_run(const int port)
-{
- enum usb_tc_state start_state;
-
- if (!pd_timer_is_expired(port, TC_TIMER_TIMEOUT))
- return;
-
- /*
- * If we transitioned to error recovery as the first state and we
- * didn't brown out, we don't need to reinitialized the tc statemachine
- * because we just did that. So transition to the state directly.
- */
- if (tc[port].ctx.previous == NULL) {
- set_state_tc(port, drp_state[port] == PD_DRP_FORCE_SOURCE ?
- TC_UNATTACHED_SRC : TC_UNATTACHED_SNK);
- return;
- }
-
- /*
- * If try src support is active (e.g. in S0). Then try to become the
- * SRC, otherwise we should try to be the sink.
- */
- start_state = TC_UNATTACHED_SNK;
- if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC))
- if (is_try_src_enabled(port) ||
- drp_state[port] == PD_DRP_FORCE_SOURCE)
- start_state = TC_UNATTACHED_SRC;
-
- restart_tc_sm(port, start_state);
-}
-
-static void tc_error_recovery_exit(const int port)
-{
- pd_timer_disable(port, TC_TIMER_TIMEOUT);
-}
-
-/**
- * Unattached.SNK
- */
-static void tc_unattached_snk_entry(const int port)
-{
- enum pd_data_role prev_data_role;
-
- if (get_last_state_tc(port) != TC_UNATTACHED_SRC) {
- tc_detached(port);
- print_current_state(port);
- }
-
- /*
- * We are in an unattached state and considering to be a SNK
- * searching for a SRC partner. We set the CC pull value to
- * to indicate our intent to be SNK in hopes a partner SRC
- * will is there to attach to.
- *
- * Both CC1 and CC2 pins shall be independently terminated to
- * ground through Rd.
- *
- * Restore default current limit Rp in case we swap to source
- *
- * Run any debug detaches needed before setting CC, as some TCPCs may
- * require we set CC Open before changing power roles with a debug
- * accessory.
- */
- tcpm_debug_detach(port);
- typec_select_pull(port, TYPEC_CC_RD);
- typec_select_src_current_limit_rp(port,
- typec_get_default_current_limit_rp(port));
- typec_update_cc(port);
-
-
- prev_data_role = tc[port].data_role;
- tc[port].data_role = PD_ROLE_DISCONNECTED;
- /*
- * When data role set events are used to enable BC1.2, then CC
- * detach events are used to notify BC1.2 that it can be powered
- * down.
- */
- bc12_role_change_handler(port, prev_data_role, tc[port].data_role);
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER))
- charge_manager_update_dualrole(port, CAP_UNKNOWN);
-
- tc_set_partner_role(port, PPC_DEV_DISCONNECTED);
-
- /*
- * Indicate that the port is disconnected so the board
- * can restore state from any previous data swap.
- */
- pd_execute_data_swap(port, PD_ROLE_DISCONNECTED);
- pd_timer_enable(port, TC_TIMER_NEXT_ROLE_SWAP, PD_T_DRP_SNK);
-
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- CLR_FLAGS_ON_DISCONNECT(port);
- tc_enable_pd(port, 0);
- }
-}
-
-static void tc_unattached_snk_run(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
-
- /*
- * TODO(b/137498392): Add wait before sampling the CC
- * status after role changes
- */
-
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED)) {
- TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED);
- tc_set_data_role(port, PD_ROLE_UFP);
- /* Inform Policy Engine that hard reset is complete */
- pe_ps_reset_complete(port);
- }
- }
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- /*
- * The port shall transition to AttachWait.SNK when a Source
- * connection is detected, as indicated by the SNK.Rp state
- * on at least one of its CC pins.
- *
- * A DRP shall transition to Unattached.SRC within tDRPTransition
- * after the state of both CC pins is SNK.Open for
- * tDRP − dcSRC.DRP ∙ tDRP.
- */
- if (cc_is_rp(cc1) || cc_is_rp(cc2)) {
- /* Connection Detected */
- set_state_tc(port, TC_ATTACH_WAIT_SNK);
- return;
- }
-
- /*
- * Debounce the CC open status. Some TCPC needs time to get the CC
- * status valid. Before that, CC open is reported by default. Wait
- * to make sure the CC is really open. Reuse the role toggle timer.
- */
- if (!pd_timer_is_expired(port, TC_TIMER_NEXT_ROLE_SWAP))
- return;
-
- /*
- * Initialize type-C supplier current limits to 0. The charge
- * manage is now seeded if it was not.
- */
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER))
- typec_set_input_current_limit(port, 0, 0);
-
- /*
- * Attempt TCPC auto DRP toggle if it is
- * not already auto toggling.
- */
- if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) &&
- drp_state[port] == PD_DRP_TOGGLE_ON &&
- tcpm_auto_toggle_supported(port)) {
- set_state_tc(port, TC_DRP_AUTO_TOGGLE);
- } else if (drp_state[port] == PD_DRP_TOGGLE_ON) {
- /* DRP Toggle. The timer was checked above. */
- set_state_tc(port, TC_UNATTACHED_SRC);
- } else if (IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER) &&
- (drp_state[port] == PD_DRP_FORCE_SINK ||
- drp_state[port] == PD_DRP_TOGGLE_OFF)) {
- set_state_tc(port, TC_LOW_POWER_MODE);
- }
-}
-
-static void tc_unattached_snk_exit(const int port)
-{
- pd_timer_disable(port, TC_TIMER_NEXT_ROLE_SWAP);
-}
-
-/**
- * AttachWait.SNK
- *
- * Super State Entry Actions:
- * Vconn Off
- * Place Rd on CC
- * Set power role to SINK
- */
-static void tc_attach_wait_snk_entry(const int port)
-{
- print_current_state(port);
-
- tc[port].cc_state = PD_CC_UNSET;
-}
-
-static void tc_attach_wait_snk_run(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
- enum pd_cc_states new_cc_state;
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- if (cc_is_rp(cc1) && cc_is_rp(cc2) && board_is_dts_port(port))
- new_cc_state = PD_CC_DFP_DEBUG_ACC;
- else if (cc_is_rp(cc1) || cc_is_rp(cc2))
- new_cc_state = PD_CC_DFP_ATTACHED;
- else
- new_cc_state = PD_CC_NONE;
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- pd_timer_enable(port, TC_TIMER_CC_DEBOUNCE, PD_T_CC_DEBOUNCE);
- pd_timer_enable(port, TC_TIMER_PD_DEBOUNCE, PD_T_PD_DEBOUNCE);
- tc[port].cc_state = new_cc_state;
- return;
- }
-
- /*
- * A DRP shall transition to Unattached.SRC when the state of both
- * the CC1 and CC2 pins is SNK.Open for at least tPDDebounce, however
- * when DRP state prevents switch to SRC the next state should be
- * Unattached.SNK.
- */
- if (new_cc_state == PD_CC_NONE &&
- pd_timer_is_expired(port, TC_TIMER_PD_DEBOUNCE)) {
- /* We are detached */
- if (drp_state[port] == PD_DRP_TOGGLE_OFF
- || drp_state[port] == PD_DRP_FREEZE
- || drp_state[port] == PD_DRP_FORCE_SINK)
- set_state_tc(port, TC_UNATTACHED_SNK);
- else
- set_state_tc(port, TC_UNATTACHED_SRC);
- return;
- }
-
- /* Wait for CC debounce */
- if (!pd_timer_is_expired(port, TC_TIMER_CC_DEBOUNCE))
- return;
-
- /*
- * The port shall transition to Attached.SNK after the state of only
- * one of the CC1 or CC2 pins is SNK.Rp for at least tCCDebounce and
- * VBUS is detected.
- *
- * A DRP that strongly prefers the Source role may optionally
- * transition to Try.SRC instead of Attached.SNK when the state of only
- * one CC pin has been SNK.Rp for at least tCCDebounce and VBUS is
- * detected.
- *
- * If the port supports Debug Accessory Mode, the port shall transition
- * to DebugAccessory.SNK if the state of both the CC1 and CC2 pins is
- * SNK.Rp for at least tCCDebounce and VBUS is detected.
- */
- if (pd_is_vbus_present(port)) {
- if (new_cc_state == PD_CC_DFP_ATTACHED) {
- if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC) &&
- is_try_src_enabled(port))
- set_state_tc(port, TC_TRY_SRC);
- else
- set_state_tc(port, TC_ATTACHED_SNK);
- } else {
- /* new_cc_state is PD_CC_DFP_DEBUG_ACC */
- CPRINTS("C%d: Debug accessory detected", port);
- TC_SET_FLAG(port, TC_FLAGS_TS_DTS_PARTNER);
- set_state_tc(port, TC_ATTACHED_SNK);
- }
-
- if (IS_ENABLED(CONFIG_USB_PE_SM) &&
- IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
- hook_call_deferred(&pd_usb_billboard_deferred_data,
- PD_T_AME);
- }
- }
-}
-
-static void tc_attach_wait_snk_exit(const int port)
-{
- pd_timer_disable(port, TC_TIMER_CC_DEBOUNCE);
- pd_timer_disable(port, TC_TIMER_PD_DEBOUNCE);
-}
-
-/**
- * Attached.SNK, shared with Debug Accessory.SNK
- */
-static void tc_attached_snk_entry(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
-
- print_current_state(port);
-
- /*
- * Known state of attach is SNK. We need to apply this pull value
- * to make it set in hardware at the correct time but set the common
- * pull here.
- *
- * Both CC1 and CC2 pins shall be independently terminated to
- * ground through Rd.
- */
- typec_select_pull(port, TYPEC_CC_RD);
-
- /* Inform the PPC and OCP module that a source is connected */
- tc_set_partner_role(port, PPC_DEV_SRC);
-
- if (IS_ENABLED(CONFIG_USB_PE_SM) &&
- TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
- /* Flipping power role - Disable AutoDischargeDisconnect */
- tcpm_enable_auto_discharge_disconnect(port, 0);
-
- /* Apply Rd */
- typec_update_cc(port);
-
- /* Change role to sink */
- tc_set_power_role(port, PD_ROLE_SINK);
- tcpm_set_msg_header(port, tc[port].power_role,
- tc[port].data_role);
-
- /*
- * Maintain VCONN supply state, whether ON or OFF, and its
- * data role / usb mux connections. Do not re-enable
- * AutoDischargeDisconnect until the swap is completed
- * and tc_pr_swap_complete is called.
- */
- } else {
- /* Get connector orientation */
- tcpm_get_cc(port, &cc1, &cc2);
- tc[port].polarity = get_snk_polarity(cc1, cc2);
- pd_set_polarity(port, tc[port].polarity);
-
- tc_set_data_role(port, PD_ROLE_UFP);
-
- hook_notify(HOOK_USB_PD_CONNECT);
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) {
- tc[port].typec_curr =
- usb_get_typec_current_limit(tc[port].polarity,
- cc1, cc2);
- typec_set_input_current_limit(port,
- tc[port].typec_curr, TYPE_C_VOLTAGE);
- /*
- * Start new connections as dedicated until source caps
- * are received, at which point the PE will update the
- * flag.
- */
- charge_manager_update_dualrole(port, CAP_DEDICATED);
- }
-
- /* Apply Rd */
- typec_update_cc(port);
-
- /*
- * Attached.SNK - enable AutoDischargeDisconnect
- * Do this after applying Rd to CC lines to avoid
- * TCPC_REG_FAULT_STATUS_AUTO_DISCHARGE_FAIL (b/171567398)
- */
- tcpm_enable_auto_discharge_disconnect(port, 1);
- }
-
- pd_timer_disable(port, TC_TIMER_CC_DEBOUNCE);
-
- /* Enable PD */
- if (IS_ENABLED(CONFIG_USB_PE_SM))
- tc_enable_pd(port, 1);
-
- if (TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) {
- tcpm_debug_accessory(port, 1);
- set_ccd_mode(port, 1);
- }
-}
-
-/*
- * Check whether Vbus has been removed on this port, accounting for some Vbus
- * debounce if FRS is enabled.
- *
- * Returns true if a new state was set and the calling run should exit.
- */
-static bool tc_snk_check_vbus_removed(const int port)
-{
- if (IS_ENABLED(CONFIG_USB_PD_FRS)) {
- /*
- * Debounce Vbus presence when FRS is enabled. Note that we may
- * lose Vbus before the FRS signal comes in to let us know
- * we're PR swapping, but we must still transition to unattached
- * within tSinkDisconnect.
- *
- * We may safely re-use the Vbus debounce timer here
- * since a PR swap would no longer be in progress when Vbus
- * removal is checked.
- */
- if (pd_check_vbus_level(port, VBUS_REMOVED)) {
- if (pd_timer_is_disabled(port,
- TC_TIMER_VBUS_DEBOUNCE)) {
- pd_timer_enable(port, TC_TIMER_VBUS_DEBOUNCE,
- PD_T_FRS_VBUS_DEBOUNCE);
- } else if (pd_timer_is_expired(port,
- TC_TIMER_VBUS_DEBOUNCE)) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return true;
- }
- } else {
- pd_timer_disable(port, TC_TIMER_VBUS_DEBOUNCE);
- }
- } else if (pd_check_vbus_level(port, VBUS_REMOVED)) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return true;
- }
-
- return false;
-}
-
-static void tc_attached_snk_run(const int port)
-{
-#ifdef CONFIG_USB_PE_SM
- /*
- * Perform Hard Reset
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED)) {
- /*
- * Wait to clear the hard reset request until Vbus has returned
- * to default (or, if it didn't return, we transition to
- * unattached)
- */
- if (tc_perform_snk_hard_reset(port))
- TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED);
-
- return;
- }
-
- /*
- * From 4.5.2.2.5.2 Exiting from Attached.SNK State:
- *
- * "A port that is not a Vconn-Powered USB Device and is not in the
- * process of a USB PD PR_Swap or a USB PD Hard Reset or a USB PD
- * FR_Swap shall transition to Unattached.SNK within tSinkDisconnect
- * when Vbus falls below vSinkDisconnect for Vbus operating at or
- * below 5 V or below vSinkDisconnectPD when negotiated by USB PD
- * to operate above 5 V."
- *
- * TODO(b/149530538): Use vSinkDisconnectPD when above 5V
- */
-
- /*
- * Debounce Vbus before we drop that we are doing a PR_Swap
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS) &&
- pd_timer_is_expired(port, TC_TIMER_VBUS_DEBOUNCE)) {
- /* PR Swap is no longer in progress */
- TC_CLR_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS);
- pd_timer_disable(port, TC_TIMER_VBUS_DEBOUNCE);
-
- /*
- * AutoDischargeDisconnect was turned off when we
- * hit Safe0V on SRC->SNK PR-Swap. We now are done
- * with the swap and should have Vbus, so re-enable
- * AutoDischargeDisconnect.
- */
- if (!pd_check_vbus_level(port, VBUS_REMOVED))
- tcpm_enable_auto_discharge_disconnect(port, 1);
- }
-
- /*
- * The sink will be powered off during a power role swap but we don't
- * want to trigger a disconnect.
- */
- if (!TC_CHK_FLAG(port, TC_FLAGS_POWER_OFF_SNK) &&
- !TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
- /*
- * Detach detection
- */
- if (tc_snk_check_vbus_removed(port))
- return;
-
- if (!pe_is_explicit_contract(port))
- sink_power_sub_states(port);
- }
-
- /*
- * PD swap commands
- */
- if (tc_get_pd_enabled(port) && prl_is_running(port)) {
- /*
- * Power Role Swap
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_REQUEST_PR_SWAP)) {
- /*
- * We may want to verify partner is applying Rd before
- * we swap. However, some TCPCs (such as TUSB422) will
- * not report the correct CC status before VBUS falls to
- * vSafe0V, so this will be problematic in the FRS case.
- */
- set_state_tc(port, TC_ATTACHED_SRC);
- return;
- }
-
- /*
- * Data Role Swap
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_REQUEST_DR_SWAP)) {
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_DR_SWAP);
-
- /* Perform Data Role Swap */
- tc_set_data_role(port,
- tc[port].data_role == PD_ROLE_UFP ?
- PD_ROLE_DFP : PD_ROLE_UFP);
- }
-
- /*
- * VCONN Swap
- * UnorientedDebugAccessory.SRC shall not drive Vconn
- */
- if (IS_ENABLED(CONFIG_USBC_VCONN) &&
- !TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) {
- if (TC_CHK_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_ON)) {
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_ON);
-
- set_vconn(port, 1);
- /*
- * Inform policy engine that vconn swap is
- * complete
- */
- pe_vconn_swap_complete(port);
- } else if (TC_CHK_FLAG(port,
- TC_FLAGS_REQUEST_VC_SWAP_OFF)) {
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_OFF);
-
- set_vconn(port, 0);
- /*
- * Inform policy engine that vconn swap is
- * complete
- */
- pe_vconn_swap_complete(port);
- }
- }
-
- if (!TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) {
- /*
- * If the port supports Charge-Through VCONN-Powered USB
- * devices, and an explicit PD contract has failed to be
- * negotiated, the port shall query the identity of the
- * cable via USB PD on SOP’
- */
- if (!pe_is_explicit_contract(port) &&
- TC_CHK_FLAG(port, TC_FLAGS_CTVPD_DETECTED)) {
- /*
- * A port that via SOP’ has detected an
- * attached Charge-Through VCONN-Powered USB
- * device shall transition to Unattached.SRC
- * if an explicit PD contract has failed to
- * be negotiated.
- */
- /* CTVPD detected */
- set_state_tc(port, TC_UNATTACHED_SRC);
- }
- }
- }
-
-#else /* CONFIG_USB_PE_SM */
-
- /* Detach detection */
- if (tc_snk_check_vbus_removed(port))
- return;
-
- /* Run Sink Power Sub-State */
- sink_power_sub_states(port);
-#endif /* CONFIG_USB_PE_SM */
-}
-
-static void tc_attached_snk_exit(const int port)
-{
- if (!TC_CHK_FLAG(port, TC_FLAGS_REQUEST_PR_SWAP)) {
- /*
- * If supplying VCONN, the port shall cease to supply
- * it within tVCONNOFF of exiting Attached.SNK if not
- * PR swapping.
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON))
- set_vconn(port, 0);
-
- /*
- * Attached.SNK exit - disable AutoDischargeDisconnect
- * NOTE: This should not happen if we are suspending. It will
- * happen in tc_cc_open_entry if that is the path we are
- * taking.
- */
- if (!TC_CHK_FLAG(port, TC_FLAGS_REQUEST_SUSPEND))
- tcpm_enable_auto_discharge_disconnect(port, 0);
- }
-
- /* Clear flags after checking Vconn status */
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_PR_SWAP | TC_FLAGS_POWER_OFF_SNK);
-
- /* Stop drawing power */
- sink_stop_drawing_current(port);
-
- if (TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER))
- tcpm_debug_detach(port);
-
- pd_timer_disable(port, TC_TIMER_CC_DEBOUNCE);
- pd_timer_disable(port, TC_TIMER_TIMEOUT);
- pd_timer_disable(port, TC_TIMER_VBUS_DEBOUNCE);
-}
-
-/**
- * Unattached.SRC
- */
-static void tc_unattached_src_entry(const int port)
-{
- enum pd_data_role prev_data_role;
-
- if (get_last_state_tc(port) != TC_UNATTACHED_SNK) {
- tc_detached(port);
- print_current_state(port);
- }
-
- /*
- * We are in an unattached state and considering to be a SRC
- * searching for a SNK partner. We set the CC pull value to
- * to indicate our intent to be SRC in hopes a partner SNK
- * will is there to attach to.
- *
- * Both CC1 and CC2 pins shall be independently terminated to
- * ground through Rp.
- *
- * Restore default current limit Rp.
- *
- * Run any debug detaches needed before setting CC, as some TCPCs may
- * require we set CC Open before changing power roles with a debug
- * accessory.
- */
- tcpm_debug_detach(port);
- typec_select_pull(port, TYPEC_CC_RP);
- typec_select_src_current_limit_rp(port,
- typec_get_default_current_limit_rp(port));
- typec_update_cc(port);
-
- prev_data_role = tc[port].data_role;
- tc[port].data_role = PD_ROLE_DISCONNECTED;
-
- /*
- * When data role set events are used to enable BC1.2, then CC
- * detach events are used to notify BC1.2 that it can be powered
- * down.
- */
- bc12_role_change_handler(port, prev_data_role, tc[port].data_role);
-
- tc_set_partner_role(port, PPC_DEV_DISCONNECTED);
-
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER))
- charge_manager_update_dualrole(port, CAP_UNKNOWN);
-
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- CLR_FLAGS_ON_DISCONNECT(port);
- tc_enable_pd(port, 0);
- }
-
- pd_timer_enable(port, TC_TIMER_NEXT_ROLE_SWAP, PD_T_DRP_SRC);
-}
-
-static void tc_unattached_src_run(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
-
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED)) {
- TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED);
- tc_set_data_role(port, PD_ROLE_DFP);
- /* Inform Policy Engine that hard reset is complete */
- pe_ps_reset_complete(port);
- }
- }
-
- if (IS_ENABLED(CONFIG_USBC_OCP)) {
- /*
- * If the port is latched off, just continue to
- * monitor for a detach.
- */
- if (usbc_ocp_is_port_latched_off(port))
- return;
- }
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- /*
- * Transition to AttachWait.SRC when:
- * 1) The SRC.Rd state is detected on either CC1 or CC2 pin or
- * 2) The SRC.Ra state is detected on both the CC1 and CC2 pins.
- *
- * A DRP shall transition to Unattached.SNK within tDRPTransition
- * after dcSRC.DRP ∙ tDRP
- */
- if (cc_is_at_least_one_rd(cc1, cc2) || cc_is_audio_acc(cc1, cc2))
- set_state_tc(port, TC_ATTACH_WAIT_SRC);
- else if (pd_timer_is_expired(port, TC_TIMER_NEXT_ROLE_SWAP) &&
- drp_state[port] != PD_DRP_FORCE_SOURCE &&
- drp_state[port] != PD_DRP_FREEZE)
- set_state_tc(port, TC_UNATTACHED_SNK);
- /*
- * Attempt TCPC auto DRP toggle
- */
- else if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) &&
- drp_state[port] == PD_DRP_TOGGLE_ON &&
- tcpm_auto_toggle_supported(port) && cc_is_open(cc1, cc2))
- set_state_tc(port, TC_DRP_AUTO_TOGGLE);
- else if (IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER) &&
- (drp_state[port] == PD_DRP_FORCE_SOURCE ||
- drp_state[port] == PD_DRP_TOGGLE_OFF))
- set_state_tc(port, TC_LOW_POWER_MODE);
-}
-
-static void tc_unattached_src_exit(const int port)
-{
- pd_timer_disable(port, TC_TIMER_NEXT_ROLE_SWAP);
-}
-
-/**
- * AttachWait.SRC
- *
- * Super State Entry Actions:
- * Vconn Off
- * Place Rp on CC
- * Set power role to SOURCE
- */
-static void tc_attach_wait_src_entry(const int port)
-{
- print_current_state(port);
-
- tc[port].cc_state = PD_CC_UNSET;
-}
-
-static void tc_attach_wait_src_run(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
- enum pd_cc_states new_cc_state;
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- if (cc_is_snk_dbg_acc(cc1, cc2) && board_is_dts_port(port)) {
- /*
- * Debug accessory.
- * A debug accessory in a non-DTS port will be
- * recognized by at_least_one_rd as UFP attached.
- */
- new_cc_state = PD_CC_UFP_DEBUG_ACC;
- } else if (cc_is_at_least_one_rd(cc1, cc2)) {
- /* UFP attached */
- new_cc_state = PD_CC_UFP_ATTACHED;
- } else if (cc_is_audio_acc(cc1, cc2)) {
- /* AUDIO Accessory not supported. Just ignore */
- new_cc_state = PD_CC_UFP_AUDIO_ACC;
- } else {
- /* No UFP */
- if (drp_state[port] == PD_DRP_FORCE_SOURCE)
- set_state_tc(port, TC_UNATTACHED_SRC);
- else
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- pd_timer_enable(port, TC_TIMER_CC_DEBOUNCE, PD_T_CC_DEBOUNCE);
- tc[port].cc_state = new_cc_state;
- return;
- }
-
- /* Wait for CC debounce */
- if (!pd_timer_is_expired(port, TC_TIMER_CC_DEBOUNCE))
- return;
-
- /*
- * The port shall transition to Attached.SRC when VBUS is at vSafe0V
- * and the SRC.Rd state is detected on exactly one of the CC1 or CC2
- * pins for at least tCCDebounce.
- *
- * If the port supports Debug Accessory Mode, it shall transition to
- * UnorientedDebugAccessory.SRC when VBUS is at vSafe0V and the SRC.Rd
- * state is detected on both the CC1 and CC2 pins for at least
- * tCCDebounce.
- */
- if (pd_check_vbus_level(port, VBUS_SAFE0V)) {
- if (new_cc_state == PD_CC_UFP_ATTACHED) {
- set_state_tc(port, TC_ATTACHED_SRC);
- return;
- } else if (new_cc_state == PD_CC_UFP_DEBUG_ACC) {
- CPRINTS("C%d: Debug accessory detected", port);
- TC_SET_FLAG(port, TC_FLAGS_TS_DTS_PARTNER);
- set_state_tc(port, TC_ATTACHED_SRC);
- return;
- }
- }
-}
-
-static void tc_attach_wait_src_exit(const int port)
-{
- pd_timer_disable(port, TC_TIMER_CC_DEBOUNCE);
-}
-
-/**
- * Attached.SRC, shared with UnorientedDebugAccessory.SRC
- */
-static void tc_attached_src_entry(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
-
- print_current_state(port);
-
- pd_timer_disable(port, TC_TIMER_TIMEOUT);
-
- /*
- * Known state of attach is SRC. We need to apply this pull value
- * to make it set in hardware at the correct time but set the common
- * pull here.
- *
- * Both CC1 and CC2 pins shall be independently terminated to
- * pulled up through Rp.
- *
- * Set selected current limit in the hardware.
- */
- typec_select_pull(port, TYPEC_CC_RP);
- typec_set_source_current_limit(port, tc[port].select_current_limit_rp);
-
- if (IS_ENABLED(CONFIG_USB_PE_SM)) {
- if (TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
- /* Change role to source */
- tc_set_power_role(port, PD_ROLE_SOURCE);
- tcpm_set_msg_header(port,
- tc[port].power_role,
- tc[port].data_role);
-
- /* Enable VBUS */
- tc_src_power_on(port);
-
- /* Apply Rp */
- typec_update_cc(port);
-
- /*
- * Maintain VCONN supply state, whether ON or OFF, and
- * its data role / usb mux connections. Do not
- * re-enable AutoDischargeDisconnect until the swap is
- * completed and tc_pr_swap_complete is called.
- */
- } else {
- /*
- * Set up CC's, Vconn, and ADD before Vbus, as per
- * Figure 4-24. DRP Initialization and Connection
- * Detection in TCPCI r2 v1.2 specification.
- */
-
- /* Get connector orientation */
- tcpm_get_cc(port, &cc1, &cc2);
- tc[port].polarity = get_src_polarity(cc1, cc2);
- pd_set_polarity(port, tc[port].polarity);
-
- /* Attached.SRC - enable AutoDischargeDisconnect */
- tcpm_enable_auto_discharge_disconnect(port, 1);
-
- /* Apply Rp */
- typec_update_cc(port);
-
- /*
- * Initial data role for sink is DFP
- * This also sets the usb mux
- */
- tc_set_data_role(port, PD_ROLE_DFP);
-
- /*
- * Start sourcing Vconn before Vbus to ensure
- * we are within USB Type-C Spec 1.4 tVconnON
- *
- * UnorientedDebugAccessory.SRC shall not drive Vconn
- */
- if (IS_ENABLED(CONFIG_USBC_VCONN) &&
- !TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER))
- set_vconn(port, 1);
-
- /* Enable VBUS */
- if (tc_src_power_on(port)) {
- /* Stop sourcing Vconn if Vbus failed */
- if (IS_ENABLED(CONFIG_USBC_VCONN))
- set_vconn(port, 0);
-
- if (IS_ENABLED(CONFIG_USBC_SS_MUX))
- usb_mux_set(port,
- USB_PD_MUX_NONE,
- USB_SWITCH_DISCONNECT,
- tc[port].polarity);
- }
-
- tc_enable_pd(port, 0);
- pd_timer_enable(port, TC_TIMER_TIMEOUT,
- MAX(PD_POWER_SUPPLY_TURN_ON_DELAY,
- PD_T_VCONN_STABLE));
- }
- } else {
- /*
- * Set up CC's, Vconn, and ADD before Vbus, as per
- * Figure 4-24. DRP Initialization and Connection
- * Detection in TCPCI r2 v1.2 specification.
- */
-
- /* Get connector orientation */
- tcpm_get_cc(port, &cc1, &cc2);
- tc[port].polarity = get_src_polarity(cc1, cc2);
- pd_set_polarity(port, tc[port].polarity);
-
- /* Attached.SRC - enable AutoDischargeDisconnect */
- tcpm_enable_auto_discharge_disconnect(port, 1);
-
- /* Apply Rp */
- typec_update_cc(port);
-
- /*
- * Initial data role for sink is DFP
- * This also sets the usb mux
- */
- tc_set_data_role(port, PD_ROLE_DFP);
-
- /*
- * Start sourcing Vconn before Vbus to ensure
- * we are within USB Type-C Spec 1.4 tVconnON
- *
- * UnorientedDebugAccessory.SRC shall not drive Vconn
- */
- if (IS_ENABLED(CONFIG_USBC_VCONN) &&
- !TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER))
- set_vconn(port, 1);
-
- /* Enable VBUS */
- if (tc_src_power_on(port)) {
- /* Stop sourcing Vconn if Vbus failed */
- if (IS_ENABLED(CONFIG_USBC_VCONN))
- set_vconn(port, 0);
-
- if (IS_ENABLED(CONFIG_USBC_SS_MUX))
- usb_mux_set(port, USB_PD_MUX_NONE,
- USB_SWITCH_DISCONNECT, tc[port].polarity);
- }
- }
-
- /* Inform PPC and OCP module that a sink is connected. */
- tc_set_partner_role(port, PPC_DEV_SNK);
-
- /* Initialize type-C supplier to seed the charge manger */
- if (IS_ENABLED(CONFIG_CHARGE_MANAGER))
- typec_set_input_current_limit(port, 0, 0);
-
- /*
- * Only notify if we're not performing a power role swap. During a
- * power role swap, the port partner is not disconnecting/connecting.
- */
- if (!TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
- hook_notify(HOOK_USB_PD_CONNECT);
- }
-
- if (TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) {
- tcpm_debug_accessory(port, 1);
- set_ccd_mode(port, 1);
- }
-
- /*
- * Some TCPCs require time to correctly return CC status after
- * changing the ROLE_CONTROL register. Due to that, we have to ignore
- * CC_NONE state until PD_T_SRC_DISCONNECT delay has elapsed.
- * From the "Universal Serial Bus Type-C Cable and Connector
- * Specification" Release 2.0 paragraph 4.5.2.2.9.2:
- * The Source shall detect the SRC.Open state within tSRCDisconnect,
- * but should detect it as quickly as possible
- */
- pd_timer_enable(port, TC_TIMER_CC_DEBOUNCE, PD_T_SRC_DISCONNECT);
-}
-
-static void tc_attached_src_run(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- if (polarity_rm_dts(tc[port].polarity))
- cc1 = cc2;
-
- if (cc1 == TYPEC_CC_VOLT_OPEN)
- tc[port].cc_state = PD_CC_NONE;
- else
- tc[port].cc_state = PD_CC_UFP_ATTACHED;
-
- /*
- * When the SRC.Open state is detected on the monitored CC pin, a DRP
- * shall transition to Unattached.SNK unless it strongly prefers the
- * Source role. In that case, it shall transition to TryWait.SNK.
- * This transition to TryWait.SNK is needed so that two devices that
- * both prefer the Source role do not loop endlessly between Source
- * and Sink. In other words, a DRP that would enter Try.SRC from
- * AttachWait.SNK shall enter TryWait.SNK for a Sink detach from
- * Attached.SRC.
- */
- if (tc[port].cc_state == PD_CC_NONE &&
- pd_timer_is_expired(port, TC_TIMER_CC_DEBOUNCE)) {
- bool tryWait;
- enum usb_tc_state new_tc_state = TC_UNATTACHED_SNK;
-
- if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC))
- tryWait = is_try_src_enabled(port) &&
- !TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER);
-
- if (drp_state[port] == PD_DRP_FORCE_SOURCE)
- new_tc_state = TC_UNATTACHED_SRC;
- else if(IS_ENABLED(CONFIG_USB_PD_TRY_SRC))
- new_tc_state = tryWait ?
- TC_TRY_WAIT_SNK : TC_UNATTACHED_SNK;
-
- set_state_tc(port, new_tc_state);
- return;
- }
-
-#ifdef CONFIG_USB_PE_SM
- /*
- * Enable PD communications after power supply has fully
- * turned on
- */
- if (pd_timer_is_expired(port, TC_TIMER_TIMEOUT)) {
- tc_enable_pd(port, 1);
- pd_timer_disable(port, TC_TIMER_TIMEOUT);
- }
-
- if (!tc_get_pd_enabled(port))
- return;
-
- /*
- * Handle Hard Reset from Policy Engine
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED)) {
- /* Ignoring Hard Resets while the power supply is resetting.*/
- if (!pd_timer_is_disabled(port, TC_TIMER_TIMEOUT) &&
- !pd_timer_is_expired(port, TC_TIMER_TIMEOUT))
- return;
-
- if (tc_perform_src_hard_reset(port))
- TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED);
-
- return;
- }
-
- /*
- * PD swap commands
- */
- if (tc_get_pd_enabled(port) && prl_is_running(port)) {
- /*
- * Power Role Swap Request
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_REQUEST_PR_SWAP)) {
- /* Clear TC_FLAGS_REQUEST_PR_SWAP on exit */
- return set_state_tc(port, TC_ATTACHED_SNK);
- }
-
- /*
- * Data Role Swap Request
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_REQUEST_DR_SWAP)) {
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_DR_SWAP);
-
- /* Perform Data Role Swap */
- tc_set_data_role(port,
- tc[port].data_role == PD_ROLE_DFP ?
- PD_ROLE_UFP : PD_ROLE_DFP);
- }
-
- /*
- * Vconn Swap Request
- * UnorientedDebugAccessory.SRC shall not drive Vconn
- */
- if (IS_ENABLED(CONFIG_USBC_VCONN) &&
- !TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER)) {
- /*
- * VCONN Swap Request
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_ON)) {
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_ON);
- set_vconn(port, 1);
- pe_vconn_swap_complete(port);
- } else if (TC_CHK_FLAG(port,
- TC_FLAGS_REQUEST_VC_SWAP_OFF)) {
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_VC_SWAP_OFF);
- set_vconn(port, 0);
- pe_vconn_swap_complete(port);
- }
- }
-
- /*
- * A DRP that supports Charge-Through VCONN-Powered USB Devices
- * shall transition to CTUnattached.SNK if the connected device
- * identifies itself as a Charge-Through VCONN-Powered USB
- * Device in its Discover Identity Command response.
- */
-
- /*
- * A DRP that supports Charge-Through VCONN-Powered USB Devices
- * shall transition to CTUnattached.SNK if the connected device
- * identifies itself as a Charge-Through VCONN-Powered USB
- * Device in its Discover Identity Command response.
- *
- * If it detects that it is connected to a VCONN-Powered USB
- * Device, the port may remove VBUS and discharge it to
- * vSafe0V, while continuing to remain in this state with VCONN
- * applied.
- */
- if (!TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER) &&
- TC_CHK_FLAG(port, TC_FLAGS_CTVPD_DETECTED)) {
-
- set_state_tc(port, TC_CT_UNATTACHED_SNK);
- }
- }
-#endif
-
- if (TC_CHK_FLAG(port, TC_FLAGS_UPDATE_CURRENT)) {
- TC_CLR_FLAG(port, TC_FLAGS_UPDATE_CURRENT);
- typec_set_source_current_limit(port,
- tc[port].select_current_limit_rp);
- pd_update_contract(port);
-
- /* Update Rp if no contract is present */
- if (!IS_ENABLED(CONFIG_USB_PE_SM) ||
- !pe_is_explicit_contract(port))
- typec_update_cc(port);
- }
-}
-
-static void tc_attached_src_exit(const int port)
-{
- /*
- * A port shall cease to supply VBUS within tVBUSOFF of exiting
- * Attached.SRC.
- */
- tc_src_power_off(port);
-
- if (!TC_CHK_FLAG(port, TC_FLAGS_REQUEST_PR_SWAP)) {
- /* Attached.SRC exit - disable AutoDischargeDisconnect */
- tcpm_enable_auto_discharge_disconnect(port, 0);
-
- /*
- * Disable VCONN if not power role swapping and
- * a CTVPD was not detected
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON) &&
- !TC_CHK_FLAG(port, TC_FLAGS_CTVPD_DETECTED))
- set_vconn(port, 0);
- }
-
- /* Clear CTVPD detected after checking for Vconn */
- TC_CLR_FLAG(port, TC_FLAGS_CTVPD_DETECTED);
-
- /* Clear PR swap flag after checking for Vconn */
- TC_CLR_FLAG(port, TC_FLAGS_REQUEST_PR_SWAP);
-
- if (TC_CHK_FLAG(port, TC_FLAGS_TS_DTS_PARTNER))
- tcpm_debug_detach(port);
-
- pd_timer_disable(port, TC_TIMER_CC_DEBOUNCE);
- pd_timer_disable(port, TC_TIMER_TIMEOUT);
-}
-
-static __maybe_unused void check_drp_connection(const int port)
-{
- enum pd_drp_next_states next_state;
- enum tcpc_cc_voltage_status cc1, cc2;
-
- TC_CLR_FLAG(port, TC_FLAGS_CHECK_CONNECTION);
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- tc[port].drp_sink_time = get_time().val;
-
- /* Get the next toggle state */
- next_state = drp_auto_toggle_next_state(&tc[port].drp_sink_time,
- tc[port].power_role, drp_state[port], cc1, cc2,
- tcpm_auto_toggle_supported(port));
-
- if (next_state == DRP_TC_DEFAULT)
- next_state = (PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE)
- ? DRP_TC_UNATTACHED_SRC
- : DRP_TC_UNATTACHED_SNK;
-
- switch (next_state) {
- case DRP_TC_UNATTACHED_SNK:
- set_state_tc(port, TC_UNATTACHED_SNK);
- break;
- case DRP_TC_ATTACHED_WAIT_SNK:
- set_state_tc(port, TC_ATTACH_WAIT_SNK);
- break;
- case DRP_TC_UNATTACHED_SRC:
- set_state_tc(port, TC_UNATTACHED_SRC);
- break;
- case DRP_TC_ATTACHED_WAIT_SRC:
- set_state_tc(port, TC_ATTACH_WAIT_SRC);
- break;
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- case DRP_TC_DRP_AUTO_TOGGLE:
- set_state_tc(port, TC_DRP_AUTO_TOGGLE);
- break;
-#endif
-
- default:
- CPRINTS("C%d: Error: DRP next state %d", port, next_state);
- break;
- }
-}
-
-/**
- * DrpAutoToggle
- */
-__maybe_unused static void tc_drp_auto_toggle_entry(const int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE))
- assert(0);
-
- print_current_state(port);
-
- /*
- * We need to ensure that we are waiting in the previous Rd or Rp state
- * for the minimum of DRP SNK or SRC so the first toggle cause by
- * transition into auto toggle doesn't violate spec timing.
- */
- pd_timer_enable(port, TC_TIMER_TIMEOUT,
- MAX(PD_T_DRP_SNK, PD_T_DRP_SRC));
-}
-
-__maybe_unused static void tc_drp_auto_toggle_run(const int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE))
- assert(0);
-
- /*
- * A timer is running, but if a connection comes in while waiting
- * then allow that to take higher priority.
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_CHECK_CONNECTION))
- check_drp_connection(port);
-
- else if (!pd_timer_is_disabled(port, TC_TIMER_TIMEOUT)) {
- if (!pd_timer_is_expired(port, TC_TIMER_TIMEOUT))
- return;
-
- pd_timer_disable(port, TC_TIMER_TIMEOUT);
- tcpm_enable_drp_toggle(port);
-
- if (IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER)) {
- set_state_tc(port, TC_LOW_POWER_MODE);
- }
- }
-}
-
-__maybe_unused static void tc_drp_auto_toggle_exit(const int port)
-{
- pd_timer_disable(port, TC_TIMER_TIMEOUT);
-}
-
-__maybe_unused static void tc_low_power_mode_entry(const int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER))
- assert(0);
-
- print_current_state(port);
- pd_timer_enable(port, TC_TIMER_LOW_POWER_TIME, PD_LPM_DEBOUNCE_US);
-}
-
-__maybe_unused static void tc_low_power_mode_run(const int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER))
- assert(0);
-
- if (TC_CHK_FLAG(port, TC_FLAGS_CHECK_CONNECTION)) {
- tc_start_event_loop(port);
- if (pd_timer_is_disabled(port, TC_TIMER_LOW_POWER_EXIT_TIME)) {
- pd_timer_enable(port, TC_TIMER_LOW_POWER_EXIT_TIME,
- PD_LPM_EXIT_DEBOUNCE_US);
- } else if (pd_timer_is_expired(port,
- TC_TIMER_LOW_POWER_EXIT_TIME)) {
- CPRINTS("C%d: Exit Low Power Mode", port);
- check_drp_connection(port);
- }
- return;
- }
-
- if (tc[port].tasks_preventing_lpm)
- pd_timer_enable(port, TC_TIMER_LOW_POWER_TIME,
- PD_LPM_DEBOUNCE_US);
-
- if (pd_timer_is_expired(port, TC_TIMER_LOW_POWER_TIME)) {
- CPRINTS("C%d: TCPC Enter Low Power Mode", port);
- TC_SET_FLAG(port, TC_FLAGS_LPM_ENGAGED);
- TC_SET_FLAG(port, TC_FLAGS_LPM_TRANSITION);
- tcpm_enter_low_power_mode(port);
- TC_CLR_FLAG(port, TC_FLAGS_LPM_TRANSITION);
- tc_pause_event_loop(port);
-
- pd_timer_disable(port, TC_TIMER_LOW_POWER_EXIT_TIME);
- }
-}
-
-__maybe_unused static void tc_low_power_mode_exit(const int port)
-{
- pd_timer_disable(port, TC_TIMER_LOW_POWER_TIME);
- pd_timer_disable(port, TC_TIMER_LOW_POWER_EXIT_TIME);
-}
-
-/**
- * Try.SRC
- *
- * Super State Entry Actions:
- * Vconn Off
- * Place Rp on CC
- * Set power role to SOURCE
- */
-#ifdef CONFIG_USB_PD_TRY_SRC
-static void tc_try_src_entry(const int port)
-{
- print_current_state(port);
-
- tc[port].cc_state = PD_CC_UNSET;
- pd_timer_enable(port, TC_TIMER_TRY_WAIT_DEBOUNCE, PD_T_DRP_TRY);
- pd_timer_enable(port, TC_TIMER_TIMEOUT, PD_T_TRY_TIMEOUT);
-
- /*
- * We are a SNK but would prefer to be a SRC. Set the pull to
- * indicate we want to be a SRC and looking for a SNK.
- *
- * Both CC1 and CC2 pins shall be independently terminated to
- * ground through Rp.
- */
- typec_select_pull(port, TYPEC_CC_RP);
-
- typec_select_src_current_limit_rp(port,
- typec_get_default_current_limit_rp(port));
-
- /* Apply Rp */
- typec_update_cc(port);
-}
-
-static void tc_try_src_run(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
- enum pd_cc_states new_cc_state;
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- if ((cc1 == TYPEC_CC_VOLT_RD && cc2 != TYPEC_CC_VOLT_RD) ||
- (cc1 != TYPEC_CC_VOLT_RD && cc2 == TYPEC_CC_VOLT_RD))
- new_cc_state = PD_CC_UFP_ATTACHED;
- else
- new_cc_state = PD_CC_NONE;
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_state = new_cc_state;
- pd_timer_enable(port, TC_TIMER_CC_DEBOUNCE, PD_T_CC_DEBOUNCE);
- }
-
- /*
- * The port shall transition to Attached.SRC when the SRC.Rd state is
- * detected on exactly one of the CC1 or CC2 pins for at least
- * tTryCCDebounce.
- */
- if (new_cc_state == PD_CC_UFP_ATTACHED &&
- pd_timer_is_expired(port, TC_TIMER_CC_DEBOUNCE))
- set_state_tc(port, TC_ATTACHED_SRC);
-
- /*
- * The port shall transition to TryWait.SNK after tDRPTry and the
- * SRC.Rd state has not been detected and VBUS is within vSafe0V,
- * or after tTryTimeout and the SRC.Rd state has not been detected.
- */
- if (new_cc_state == PD_CC_NONE) {
- if ((pd_timer_is_expired(port, TC_TIMER_TRY_WAIT_DEBOUNCE) &&
- pd_check_vbus_level(port, VBUS_SAFE0V)) ||
- pd_timer_is_expired(port, TC_TIMER_TIMEOUT)) {
- set_state_tc(port, TC_TRY_WAIT_SNK);
- }
- }
-}
-
-static void tc_try_src_exit(const int port)
-{
- pd_timer_disable(port, TC_TIMER_CC_DEBOUNCE);
- pd_timer_disable(port, TC_TIMER_TIMEOUT);
- pd_timer_disable(port, TC_TIMER_TRY_WAIT_DEBOUNCE);
-}
-
-/**
- * TryWait.SNK
- *
- * Super State Entry Actions:
- * Vconn Off
- * Place Rd on CC
- * Set power role to SINK
- */
-static void tc_try_wait_snk_entry(const int port)
-{
- print_current_state(port);
-
- tc_enable_pd(port, 0);
- tc[port].cc_state = PD_CC_UNSET;
- pd_timer_enable(port, TC_TIMER_TRY_WAIT_DEBOUNCE, PD_T_CC_DEBOUNCE);
-
- /*
- * We were a SNK, tried to be a SRC and it didn't work out. Try to
- * go back to being a SNK. Set the pull to indicate we want to be
- * a SNK and looking for a SRC.
- *
- * Both CC1 and CC2 pins shall be independently terminated to
- * ground through Rd.
- */
- typec_select_pull(port, TYPEC_CC_RD);
-
- /* Apply Rd */
- typec_update_cc(port);
-}
-
-static void tc_try_wait_snk_run(const int port)
-{
- enum tcpc_cc_voltage_status cc1, cc2;
- enum pd_cc_states new_cc_state;
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- /* We only care about CCs being open */
- if (cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_OPEN)
- new_cc_state = PD_CC_NONE;
- else
- new_cc_state = PD_CC_UNSET;
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_state = new_cc_state;
- pd_timer_enable(port, TC_TIMER_PD_DEBOUNCE, PD_T_PD_DEBOUNCE);
- }
-
- /*
- * The port shall transition to Unattached.SNK when the state of both
- * of the CC1 and CC2 pins is SNK.Open for at least tPDDebounce.
- */
- if (new_cc_state == PD_CC_NONE &&
- pd_timer_is_expired(port, TC_TIMER_PD_DEBOUNCE)) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- /*
- * The port shall transition to Attached.SNK after tCCDebounce if or
- * when VBUS is detected.
- */
- if (pd_timer_is_expired(port, TC_TIMER_TRY_WAIT_DEBOUNCE) &&
- pd_is_vbus_present(port))
- set_state_tc(port, TC_ATTACHED_SNK);
-}
-
-static void tc_try_wait_snk_exit(const int port)
-{
- pd_timer_disable(port, TC_TIMER_PD_DEBOUNCE);
- pd_timer_disable(port, TC_TIMER_TRY_WAIT_DEBOUNCE);
-}
-#endif
-
-/*
- * CTUnattached.SNK
- */
-__maybe_unused static void tc_ct_unattached_snk_entry(int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PE_SM))
- assert(0);
-
- print_current_state(port);
-
- /*
- * Both CC1 and CC2 pins shall be independently terminated to
- * ground through Rd.
- */
- typec_select_pull(port, TYPEC_CC_RD);
- typec_update_cc(port);
-
- tc[port].cc_state = PD_CC_UNSET;
-
- /* Set power role to sink */
- tc_set_power_role(port, PD_ROLE_SINK);
- tcpm_set_msg_header(port, tc[port].power_role, tc[port].data_role);
-
- /*
- * The policy engine is in the disabled state. Disable PD and
- * re-enable it
- */
- tc_enable_pd(port, 0);
-
- pd_timer_enable(port, TC_TIMER_TIMEOUT, PD_POWER_SUPPLY_TURN_ON_DELAY);
-}
-
-__maybe_unused static void tc_ct_unattached_snk_run(int port)
-{
- enum tcpc_cc_voltage_status cc1;
- enum tcpc_cc_voltage_status cc2;
- enum pd_cc_states new_cc_state;
-
- if (!IS_ENABLED(CONFIG_USB_PE_SM))
- assert(0);
-
- if (!pd_timer_is_disabled(port, TC_TIMER_TIMEOUT)) {
- if (pd_timer_is_expired(port, TC_TIMER_TIMEOUT)) {
- tc_enable_pd(port, 1);
- pd_timer_disable(port, TC_TIMER_TIMEOUT);
- } else {
- return;
- }
- }
-
- /* Wait until Protocol Layer is ready */
- if (!prl_is_running(port))
- return;
-
- /*
- * Hard Reset is sent when the PE layer is disabled due to a
- * CTVPD connection.
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED)) {
- TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED);
- /* Nothing to do. Just signal hard reset completion */
- pe_ps_reset_complete(port);
- }
-
- /* Check for connection */
- tcpm_get_cc(port, &cc1, &cc2);
-
- /* We only care about CCs being open */
- if (cc1 == TYPEC_CC_VOLT_OPEN && cc2 == TYPEC_CC_VOLT_OPEN)
- new_cc_state = PD_CC_NONE;
- else
- new_cc_state = PD_CC_UNSET;
-
- /* Debounce the cc state */
- if (new_cc_state != tc[port].cc_state) {
- tc[port].cc_state = new_cc_state;
- pd_timer_enable(port, TC_TIMER_CC_DEBOUNCE, PD_T_VPDDETACH);
- }
-
- /*
- * The port shall transition to Unattached.SNK if the state of
- * the CC pin is SNK.Open for tVPDDetach after VBUS is vSafe0V.
- */
- else if (pd_timer_is_expired(port, TC_TIMER_CC_DEBOUNCE)) {
- if (new_cc_state == PD_CC_NONE &&
- pd_check_vbus_level(port, VBUS_SAFE0V)) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
- }
-
- /*
- * The port shall transition to CTAttached.SNK when VBUS is detected.
- */
- if (pd_is_vbus_present(port))
- set_state_tc(port, TC_CT_ATTACHED_SNK);
-}
-
-__maybe_unused static void tc_ct_unattached_snk_exit(int port)
-{
- pd_timer_disable(port, TC_TIMER_CC_DEBOUNCE);
- pd_timer_disable(port, TC_TIMER_TIMEOUT);
-}
-
-/**
- * CTAttached.SNK
- */
-__maybe_unused static void tc_ct_attached_snk_entry(int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PE_SM))
- assert(0);
-
- print_current_state(port);
-
- /* The port shall reject a VCONN swap request. */
- TC_SET_FLAG(port, TC_FLAGS_REJECT_VCONN_SWAP);
-}
-
-__maybe_unused static void tc_ct_attached_snk_run(int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PE_SM))
- assert(0);
-
- /*
- * Hard Reset is sent when the PE layer is disabled due to a
- * CTVPD connection.
- */
- if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED)) {
- TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED);
- /* Nothing to do. Just signal hard reset completion */
- pe_ps_reset_complete(port);
- }
-
- /*
- * A port that is not in the process of a USB PD Hard Reset shall
- * transition to CTUnattached.SNK within tSinkDisconnect when VBUS
- * falls below vSinkDisconnect
- */
- if (pd_check_vbus_level(port, VBUS_REMOVED)) {
- set_state_tc(port, TC_CT_UNATTACHED_SNK);
- return;
- }
-
- /*
- * The port shall operate in one of the Sink Power Sub-States
- * and remain within the Sink Power Sub-States, until either VBUS is
- * removed or a USB PD contract is established with the source.
- */
- if (!pe_is_explicit_contract(port))
- sink_power_sub_states(port);
-}
-
-__maybe_unused static void tc_ct_attached_snk_exit(int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PE_SM))
- assert(0);
-
- /* Stop drawing power */
- sink_stop_drawing_current(port);
-
- TC_CLR_FLAG(port, TC_FLAGS_REJECT_VCONN_SWAP);
-}
-
-/**
- * Super State CC_RD
- */
-static void tc_cc_rd_entry(const int port)
-{
- /* Disable VCONN */
- if (IS_ENABLED(CONFIG_USBC_VCONN))
- set_vconn(port, 0);
-
- /* Set power role to sink */
- tc_set_power_role(port, PD_ROLE_SINK);
- tcpm_set_msg_header(port, tc[port].power_role, tc[port].data_role);
-}
-
-
-/**
- * Super State CC_RP
- */
-static void tc_cc_rp_entry(const int port)
-{
- /* Disable VCONN */
- if (IS_ENABLED(CONFIG_USBC_VCONN))
- set_vconn(port, 0);
-
- /* Set power role to source */
- tc_set_power_role(port, PD_ROLE_SOURCE);
- tcpm_set_msg_header(port, tc[port].power_role, tc[port].data_role);
-}
-
-/**
- * Super State CC_OPEN
- */
-static void tc_cc_open_entry(const int port)
-{
- /* Ensure we are not sourcing Vbus */
- tc_src_power_off(port);
-
- /* Disable VCONN */
- set_vconn(port, 0);
-
- /*
- * Ensure we disable discharging before setting CC lines to open.
- * If we were sourcing above, then we already drained Vbus. If partner
- * is sourcing Vbus they will drain Vbus if they are PD-capable. This
- * should only be done if a battery is present as a batteryless
- * device will brown out when AutoDischargeDisconnect is disabled and
- * we do not want this to happen until the set_cc open/open to make
- * sure the TCPC has managed its internal states for disconnecting
- * the only source of power it has.
- */
- if (battery_is_present())
- tcpm_enable_auto_discharge_disconnect(port, 0);
-
- /*
- * We may brown out after applying CC open, so flush console first.
- * Console flush can take a long time, so if we aren't in danger of
- * browning out, don't do it so we can meet certain compliance timing
- * requirements.
- */
- CPRINTS("C%d: Applying CC Open!", port);
- if (!battery_is_present())
- cflush();
-
- /* Remove terminations from CC */
- typec_select_pull(port, TYPEC_CC_OPEN);
- typec_update_cc(port);
-
- tc_set_partner_role(port, PPC_DEV_DISCONNECTED);
- tc_detached(port);
-}
-
-void tc_set_debug_level(enum debug_level debug_level)
-{
-#ifndef CONFIG_USB_PD_DEBUG_LEVEL
- tc_debug_level = debug_level;
-#endif
-}
-
-void tc_usb_firmware_fw_update_limited_run(int port)
-{
- TC_SET_FLAG(port, TC_FLAGS_USB_RETIMER_FW_UPDATE_LTD_RUN);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void tc_usb_firmware_fw_update_run(int port)
-{
- TC_SET_FLAG(port, TC_FLAGS_USB_RETIMER_FW_UPDATE_RUN);
- task_wake(PD_PORT_TO_TASK_ID(port));
-}
-
-void tc_run(const int port)
-{
- /*
- * If pd_set_suspend set TC_FLAGS_REQUEST_SUSPEND, go directly to
- * TC_DISABLED.
- */
- if (get_state_tc(port) != TC_DISABLED
- && TC_CHK_FLAG(port, TC_FLAGS_REQUEST_SUSPEND)) {
- /* Invalidate a contract, if there is one */
- if (IS_ENABLED(CONFIG_USB_PE_SM))
- pe_invalidate_explicit_contract(port);
-
- set_state_tc(port, TC_DISABLED);
- }
-
- /* If error recovery has been requested, transition now */
- if (TC_CHK_FLAG(port, TC_FLAGS_REQUEST_ERROR_RECOVERY)) {
- if (IS_ENABLED(CONFIG_USB_PE_SM))
- pe_invalidate_explicit_contract(port);
- set_state_tc(port, TC_ERROR_RECOVERY);
- }
-
- if (IS_ENABLED(CONFIG_USBC_RETIMER_FW_UPDATE)) {
- if (TC_CHK_FLAG(port, TC_FLAGS_USB_RETIMER_FW_UPDATE_RUN)) {
- TC_CLR_FLAG(port, TC_FLAGS_USB_RETIMER_FW_UPDATE_RUN);
- usb_retimer_fw_update_process_op_cb(port);
- }
- }
-
- run_state(port, &tc[port].ctx);
-}
-
-static void pd_chipset_resume(void)
-{
- int i;
-
- for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) {
- if(IS_ENABLED(CONFIG_USB_PE_SM))
- pd_resume_check_pr_swap_needed(i);
-
- pd_set_dual_role_and_event(i,
- PD_DRP_TOGGLE_ON,
- PD_EVENT_UPDATE_DUAL_ROLE
- | PD_EVENT_POWER_STATE_CHANGE);
- }
-
- CPRINTS("PD:S3->S0");
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, pd_chipset_resume, HOOK_PRIO_DEFAULT);
-
-static void pd_chipset_suspend(void)
-{
- int i;
-
- for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) {
- pd_set_dual_role_and_event(i,
- pd_get_drp_state_in_suspend(),
- PD_EVENT_UPDATE_DUAL_ROLE
- | PD_EVENT_POWER_STATE_CHANGE);
- }
-
- CPRINTS("PD:S0->S3");
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, pd_chipset_suspend, HOOK_PRIO_DEFAULT);
-
-static void pd_chipset_reset(void)
-{
- int i;
-
- if (!IS_ENABLED(CONFIG_USB_PE_SM))
- return;
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++) {
- enum tcpci_msg_type tx;
-
- /* Do not notify the AP of irrelevant past Hard Resets. */
- pd_clear_events(i, PD_STATUS_EVENT_HARD_RESET);
-
- /*
- * Re-set events for SOP and SOP' discovery complete so the
- * kernel knows to consume discovery information for them.
- */
- for (tx = TCPCI_MSG_SOP; tx <= TCPCI_MSG_SOP_PRIME; tx++) {
- if (pd_get_identity_discovery(i, tx) != PD_DISC_NEEDED
- && pd_get_svids_discovery(i, tx) != PD_DISC_NEEDED
- && pd_get_modes_discovery(i, tx) != PD_DISC_NEEDED)
- pd_notify_event(i, tx == TCPCI_MSG_SOP ?
- PD_STATUS_EVENT_SOP_DISC_DONE :
- PD_STATUS_EVENT_SOP_PRIME_DISC_DONE);
- }
-
- /* Exit mode so AP can enter mode again after reset */
- if (IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY))
- dpm_set_mode_exit_request(i);
- }
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESET, pd_chipset_reset, HOOK_PRIO_DEFAULT);
-
-static void pd_chipset_startup(void)
-{
- int i;
-
- for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) {
- TC_SET_FLAG(i, TC_FLAGS_UPDATE_USB_MUX);
- pd_set_dual_role_and_event(i,
- pd_get_drp_state_in_suspend(),
- PD_EVENT_UPDATE_DUAL_ROLE
- | PD_EVENT_POWER_STATE_CHANGE);
- /*
- * Request port discovery to restore any
- * alt modes.
- * TODO(b/158042116): Do not start port discovery if there
- * is an existing connection.
- */
- if (IS_ENABLED(CONFIG_USB_PE_SM))
- pd_dpm_request(i, DPM_REQUEST_PORT_DISCOVERY);
- }
-
- CPRINTS("PD:S5->S3");
-}
-DECLARE_HOOK(HOOK_CHIPSET_STARTUP, pd_chipset_startup, HOOK_PRIO_DEFAULT);
-
-static void pd_chipset_shutdown(void)
-{
- int i;
-
- for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) {
- TC_SET_FLAG(i, TC_FLAGS_UPDATE_USB_MUX);
- pd_set_dual_role_and_event(i,
- PD_DRP_FORCE_SINK,
- PD_EVENT_UPDATE_DUAL_ROLE
- | PD_EVENT_POWER_STATE_CHANGE);
- }
-
- CPRINTS("PD:S3->S5");
-}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pd_chipset_shutdown, HOOK_PRIO_DEFAULT);
-
-static void pd_set_power_change(void)
-{
- int i;
-
- for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) {
- task_set_event(PD_PORT_TO_TASK_ID(i),
- PD_EVENT_POWER_STATE_CHANGE);
- }
-}
-DECLARE_DEFERRED(pd_set_power_change);
-
-static void pd_chipset_hard_off(void)
-{
- /*
- * Wait 1 second to check our Vconn sourcing status, as the power rails
- * which were supporting it may take some time to change after entering
- * G3.
- */
- hook_call_deferred(&pd_set_power_change_data, 1 * SECOND);
-}
-DECLARE_HOOK(HOOK_CHIPSET_HARD_OFF, pd_chipset_hard_off, HOOK_PRIO_DEFAULT);
-
-/*
- * Type-C State Hierarchy (Sub-States are listed inside the boxes)
- *
- * |TC_CC_RD --------------| |TC_CC_RP ------------------------|
- * | | | |
- * | TC_UNATTACHED_SNK | | TC_UNATTACHED_SRC |
- * | TC_ATTACH_WAIT_SNK | | TC_ATTACH_WAIT_SRC |
- * | TC_TRY_WAIT_SNK | | TC_TRY_SRC |
- * |-----------------------| |---------------------------------|
- *
- * |TC_CC_OPEN -----------|
- * | |
- * | TC_DISABLED |
- * | TC_ERROR_RECOVERY |
- * |----------------------|
- *
- * TC_ATTACHED_SNK TC_ATTACHED_SRC TC_DRP_AUTO_TOGGLE TC_LOW_POWER_MODE
- *
- */
-static __const_data const struct usb_state tc_states[] = {
- /* Super States */
- [TC_CC_OPEN] = {
- .entry = tc_cc_open_entry,
- },
- [TC_CC_RD] = {
- .entry = tc_cc_rd_entry,
- },
- [TC_CC_RP] = {
- .entry = tc_cc_rp_entry,
- },
- /* Normal States */
- [TC_DISABLED] = {
- .entry = tc_disabled_entry,
- .run = tc_disabled_run,
- .exit = tc_disabled_exit,
- .parent = &tc_states[TC_CC_OPEN],
- },
- [TC_ERROR_RECOVERY] = {
- .entry = tc_error_recovery_entry,
- .run = tc_error_recovery_run,
- .exit = tc_error_recovery_exit,
- .parent = &tc_states[TC_CC_OPEN],
- },
- [TC_UNATTACHED_SNK] = {
- .entry = tc_unattached_snk_entry,
- .run = tc_unattached_snk_run,
- .exit = tc_unattached_snk_exit,
- .parent = &tc_states[TC_CC_RD],
- },
- [TC_ATTACH_WAIT_SNK] = {
- .entry = tc_attach_wait_snk_entry,
- .run = tc_attach_wait_snk_run,
- .exit = tc_attach_wait_snk_exit,
- .parent = &tc_states[TC_CC_RD],
- },
- [TC_ATTACHED_SNK] = {
- .entry = tc_attached_snk_entry,
- .run = tc_attached_snk_run,
- .exit = tc_attached_snk_exit,
- },
- [TC_UNATTACHED_SRC] = {
- .entry = tc_unattached_src_entry,
- .run = tc_unattached_src_run,
- .exit = tc_unattached_src_exit,
- .parent = &tc_states[TC_CC_RP],
- },
- [TC_ATTACH_WAIT_SRC] = {
- .entry = tc_attach_wait_src_entry,
- .run = tc_attach_wait_src_run,
- .exit = tc_attach_wait_src_exit,
- .parent = &tc_states[TC_CC_RP],
- },
- [TC_ATTACHED_SRC] = {
- .entry = tc_attached_src_entry,
- .run = tc_attached_src_run,
- .exit = tc_attached_src_exit,
- },
-#ifdef CONFIG_USB_PD_TRY_SRC
- [TC_TRY_SRC] = {
- .entry = tc_try_src_entry,
- .run = tc_try_src_run,
- .exit = tc_try_src_exit,
- .parent = &tc_states[TC_CC_RP],
- },
- [TC_TRY_WAIT_SNK] = {
- .entry = tc_try_wait_snk_entry,
- .run = tc_try_wait_snk_run,
- .exit = tc_try_wait_snk_exit,
- .parent = &tc_states[TC_CC_RD],
- },
-#endif /* CONFIG_USB_PD_TRY_SRC */
-#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
- [TC_DRP_AUTO_TOGGLE] = {
- .entry = tc_drp_auto_toggle_entry,
- .run = tc_drp_auto_toggle_run,
- .exit = tc_drp_auto_toggle_exit,
- },
-#endif /* CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE */
-#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
- [TC_LOW_POWER_MODE] = {
- .entry = tc_low_power_mode_entry,
- .run = tc_low_power_mode_run,
- .exit = tc_low_power_mode_exit,
- },
-#endif /* CONFIG_USB_PD_TCPC_LOW_POWER */
-#ifdef CONFIG_USB_PE_SM
- [TC_CT_UNATTACHED_SNK] = {
- .entry = tc_ct_unattached_snk_entry,
- .run = tc_ct_unattached_snk_run,
- .exit = tc_ct_unattached_snk_exit,
- },
- [TC_CT_ATTACHED_SNK] = {
- .entry = tc_ct_attached_snk_entry,
- .run = tc_ct_attached_snk_run,
- .exit = tc_ct_attached_snk_exit,
- },
-#endif
-};
-
-#if defined(TEST_BUILD) && defined(USB_PD_DEBUG_LABELS)
-const struct test_sm_data test_tc_sm_data[] = {
- {
- .base = tc_states,
- .size = ARRAY_SIZE(tc_states),
- .names = tc_state_names,
- .names_size = ARRAY_SIZE(tc_state_names),
- },
-};
-const int test_tc_sm_data_size = ARRAY_SIZE(test_tc_sm_data);
-#endif
diff --git a/common/usbc/usb_tc_vpd_sm.c b/common/usbc/usb_tc_vpd_sm.c
deleted file mode 100644
index f230d15003..0000000000
--- a/common/usbc/usb_tc_vpd_sm.c
+++ /dev/null
@@ -1,430 +0,0 @@
-/* Copyright 2019 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.
- */
-
-#include "common.h"
-#include "console.h"
-#include "system.h"
-#include "task.h"
-#include "tcpm/tcpm.h"
-#include "usb_pd.h"
-#include "usb_tc_sm.h"
-#include "usb_sm.h"
-#include "vpd_api.h"
-
-/* USB Type-C VCONN Powered Device module */
-
-#ifdef CONFIG_COMMON_RUNTIME
-#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USB, format, ## args)
-#else /* CONFIG_COMMON_RUNTIME */
-#define CPRINTF(format, args...)
-#define CPRINTS(format, args...)
-#endif
-
-/* Type-C Layer Flags */
-#define TC_FLAGS_VCONN_ON BIT(0)
-
-/**
- * This is the Type-C Port object that contains information needed to
- * implement a VCONN Powered Device.
- */
-static struct type_c {
- /* state machine context */
- struct sm_ctx ctx;
- /* Higher-level power deliver state machines are enabled if true. */
- uint8_t pd_enable;
- /* port flags, see TC_FLAGS_* */
- uint32_t flags;
- /* Time a port shall wait before it can determine it is attached */
- uint64_t cc_debounce;
- /* VPD host port cc state */
- enum pd_cc_states host_cc_state;
- uint8_t ct_cc;
-} tc[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-/* List of all TypeC-level states */
-enum usb_tc_state {
- /* Normal States */
- TC_DISABLED,
- TC_UNATTACHED_SNK,
- TC_ATTACH_WAIT_SNK,
- TC_ATTACHED_SNK,
- /* Super States */
- TC_VBUS_CC_ISO,
- TC_HOST_RARD,
- TC_HOST_OPEN,
-};
-/* Forward declare the full list of states. This is indexed by usb_tc_state */
-static const struct usb_state tc_states[];
-
-/* List of human readable state names for console debugging */
-__maybe_unused static const char * const tc_state_names[] = {
-#ifdef CONFIG_COMMON_RUNTIME
- [TC_DISABLED] = "Disabled",
- [TC_UNATTACHED_SNK] = "Unattached.SNK",
- [TC_ATTACH_WAIT_SNK] = "AttachWait.SNK",
- [TC_ATTACHED_SNK] = "Attached.SNK",
-#endif
-};
-
-/* Forward declare private, common functions */
-static void set_state_tc(const int port, enum usb_tc_state new_state);
-
-/*
- * TCPC CC/Rp management
- *
- * Stub for linking purposes.
- * This is not supported for vpd, it uses a different mechanism to update
- * cc values.
- */
-void typec_select_pull(int port, enum tcpc_cc_pull pull)
-{
-}
-void typec_select_src_current_limit_rp(int port, enum tcpc_rp_value rp)
-{
-}
-void typec_select_src_collision_rp(int port, enum tcpc_rp_value rp)
-{
-}
-int typec_update_cc(int port)
-{
- return EC_SUCCESS;
-}
-
-/* Public TypeC functions */
-
-void tc_state_init(int port)
-{
- int res = 0;
-
- res = tcpm_init(port);
-
- CPRINTS("C%d: init %s", port, res ? "failed" : "ready");
-
- /* Disable TCPC RX until connection is established */
- tcpm_set_rx_enable(port, 0);
-
- set_state_tc(port, res ? TC_DISABLED : TC_UNATTACHED_SNK);
-
- /* Disable pd state machines */
- tc[port].pd_enable = 0;
- tc[port].flags = 0;
-}
-
-enum pd_power_role pd_get_power_role(int port)
-{
- /* Vconn power device is always the sink */
- return PD_ROLE_SINK;
-}
-
-enum pd_cable_plug tc_get_cable_plug(int port)
-{
- /* Vconn power device is always the cable */
- return PD_PLUG_FROM_CABLE;
-}
-
-enum pd_data_role pd_get_data_role(int port)
-{
- /* Vconn power device doesn't have a data role, but UFP match SNK */
- return PD_ROLE_UFP;
-}
-
-/* Note tc_set_power_role and tc_set_data_role are unimplemented */
-
-uint8_t tc_get_polarity(int port)
-{
- /* Does not track polarity yet */
- return 0;
-}
-
-uint8_t tc_get_pd_enabled(int port)
-{
- return tc[port].pd_enable;
-}
-
-void tc_event_check(int port, int evt)
-{
- /* Do Nothing */
-}
-
-/*
- * Private Functions
- */
-
-/* Set the TypeC state machine to a new state. */
-static void set_state_tc(const int port, const enum usb_tc_state new_state)
-{
- set_state(port, &tc[port].ctx, &tc_states[new_state]);
-}
-
-/* Get the current TypeC state. */
-test_export_static enum usb_tc_state get_state_tc(const int port)
-{
- return tc[port].ctx.current - &tc_states[0];
-}
-
-test_mockable_static void print_current_state(const int port)
-{
- CPRINTS("C%d: %s", port, tc_state_names[get_state_tc(port)]);
-}
-
-/**
- * Disabled
- *
- * Super State Entries:
- * Enable mcu communication
- * Remove the terminations from Host CC
- */
-static void tc_disabled_entry(const int port)
-{
- print_current_state(port);
-}
-
-static void tc_disabled_run(const int port)
-{
- task_wait_event(-1);
-}
-
-void pd_set_suspend(int port, int suspend)
-{
- /*
- * This shouldn't happen. If it does, we need to send an event to the
- * PD task to put the SM into the disabled state. It is not safe to
- * directly set_state here since this may be in another task.
- */
- assert(false);
-}
-
-static void tc_disabled_exit(const int port)
-{
- if (!IS_ENABLED(CONFIG_USB_PD_TCPC)) {
- if (tcpm_init(port) != 0) {
- CPRINTS("C%d: restart failed!", port);
- return;
- }
- }
-
- CPRINTS("C%d: resumed!", port);
-}
-
-/**
- * Unattached.SNK
- *
- * Super State Entry:
- * Enable mcu communication
- * Place Ra on VCONN and Rd on Host CC
- */
-static void tc_unattached_snk_entry(const int port)
-{
- print_current_state(port);
-}
-
-static void tc_unattached_snk_run(const int port)
-{
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- /*
- * Transition to AttachWait.SNK when a Source connection is
- * detected, as indicated by the SNK.Rp state on its Host-side
- * port’s CC pin.
- */
- if (cc_is_rp(host_cc))
- set_state_tc(port, TC_ATTACH_WAIT_SNK);
-}
-
-/**
- * AttachedWait.SNK
- *
- * Super State Entry:
- * Enable mcu communication
- * Place Ra on VCONN and Rd on Host CC
- */
-static void tc_attach_wait_snk_entry(const int port)
-{
- print_current_state(port);
-
- /* Forces an initial debounce in run function */
- tc[port].host_cc_state = -1;
-}
-
-static void tc_attach_wait_snk_run(const int port)
-{
- int host_new_cc_state;
- int host_cc;
-
- /* Check Host CC for connection */
- vpd_host_get_cc(&host_cc);
-
- if (cc_is_rp(host_cc))
- host_new_cc_state = PD_CC_DFP_ATTACHED;
- else
- host_new_cc_state = PD_CC_NONE;
-
- /* Debounce the Host CC state */
- if (tc[port].host_cc_state != host_new_cc_state) {
- tc[port].host_cc_state = host_new_cc_state;
- if (host_new_cc_state == PD_CC_DFP_ATTACHED)
- tc[port].cc_debounce = get_time().val +
- PD_T_CC_DEBOUNCE;
- else
- tc[port].cc_debounce = get_time().val +
- PD_T_PD_DEBOUNCE;
-
- return;
- }
-
- /* Wait for Host CC debounce */
- if (get_time().val < tc[port].cc_debounce)
- return;
-
- /*
- * A VCONN-Powered USB Device shall transition to
- * Attached.SNK after the state of the Host-side port’s CC pin is
- * SNK.Rp for at least tCCDebounce and either host-side VCONN or
- * VBUS is detected.
- *
- * Transition to Unattached.SNK when the state of both the CC1 and
- * CC2 pins is SNK.Open for at least tPDDebounce.
- */
- if (tc[port].host_cc_state == PD_CC_DFP_ATTACHED &&
- (vpd_is_vconn_present() || vpd_is_host_vbus_present()))
- set_state_tc(port, TC_ATTACHED_SNK);
- else if (tc[port].host_cc_state == PD_CC_NONE)
- set_state_tc(port, TC_UNATTACHED_SNK);
-}
-
-/**
- * Attached.SNK
- */
-static void tc_attached_snk_entry(const int port)
-{
- print_current_state(port);
-
- /* Enable PD */
- tc[port].pd_enable = 1;
- pd_set_polarity(port, 0);
-}
-
-static void tc_attached_snk_run(const int port)
-{
- /* Has host vbus and vconn been removed */
- if (!vpd_is_host_vbus_present() && !vpd_is_vconn_present()) {
- set_state_tc(port, TC_UNATTACHED_SNK);
- return;
- }
-
- if (vpd_is_vconn_present()) {
- if (!(tc[port].flags & TC_FLAGS_VCONN_ON)) {
- /* VCONN detected. Remove RA */
- vpd_host_set_pull(TYPEC_CC_RD, 0);
- tc[port].flags |= TC_FLAGS_VCONN_ON;
- }
- }
-}
-
-static void tc_attached_snk_exit(const int port)
-{
- /* Disable PD */
- tc[port].pd_enable = 0;
- tc[port].flags &= ~TC_FLAGS_VCONN_ON;
-}
-
-/**
- * Super State HOST_RARD
- */
-static void tc_host_rard_entry(const int port)
-{
- /* Place Ra on VCONN and Rd on Host CC */
- vpd_host_set_pull(TYPEC_CC_RA_RD, 0);
-}
-
-/**
- * Super State HOST_OPEN
- */
-static void tc_host_open_entry(const int port)
-{
- /* Remove the terminations from Host CC */
- vpd_host_set_pull(TYPEC_CC_OPEN, 0);
-}
-
-/**
- * Super State VBUS_CC_ISO
- */
-static void tc_vbus_cc_iso_entry(const int port)
-{
- /* Enable mcu communication and cc */
- vpd_mcu_cc_en(1);
-}
-
-void tc_run(const int port)
-{
- run_state(port, &tc[port].ctx);
-}
-
-/*
- * Type-C State Hierarchy (Sub-States are listed inside the boxes)
- *
- * | TC_VBUS_CC_ISO ----------------------------------------|
- * | |
- * | | TC_HOST_RARD -----------| | TC_HOST_OPEN ---------| |
- * | | | | | |
- * | | TC_UNATTACHED_SNK | | TC_DISABLED | |
- * | | TC_ATTACH_WAIT_SNK | |-----------------------| |
- * | |-------------------------| |
- * |--------------------------------------------------------|
- *
- * TC_ATTACHED_SNK
- */
-static const struct usb_state tc_states[] = {
- /* Super States */
- [TC_VBUS_CC_ISO] = {
- .entry = tc_vbus_cc_iso_entry,
- },
- [TC_HOST_RARD] = {
- .entry = tc_host_rard_entry,
- .parent = &tc_states[TC_VBUS_CC_ISO],
- },
- [TC_HOST_OPEN] = {
- .entry = tc_host_open_entry,
- .parent = &tc_states[TC_VBUS_CC_ISO],
- },
- /* Normal States */
- [TC_DISABLED] = {
- .entry = tc_disabled_entry,
- .run = tc_disabled_run,
- .exit = tc_disabled_exit,
- .parent = &tc_states[TC_HOST_OPEN],
- },
- [TC_UNATTACHED_SNK] = {
- .entry = tc_unattached_snk_entry,
- .run = tc_unattached_snk_run,
- .parent = &tc_states[TC_HOST_RARD],
- },
- [TC_ATTACH_WAIT_SNK] = {
- .entry = tc_attach_wait_snk_entry,
- .run = tc_attach_wait_snk_run,
- .parent = &tc_states[TC_HOST_RARD],
- },
- [TC_ATTACHED_SNK] = {
- .entry = tc_attached_snk_entry,
- .run = tc_attached_snk_run,
- .exit = tc_attached_snk_exit,
- },
-};
-
-#ifdef TEST_BUILD
-const struct test_sm_data test_tc_sm_data[] = {
- {
- .base = tc_states,
- .size = ARRAY_SIZE(tc_states),
- .names = tc_state_names,
- .names_size = ARRAY_SIZE(tc_state_names),
- },
-};
-const int test_tc_sm_data_size = ARRAY_SIZE(test_tc_sm_data);
-#endif
diff --git a/common/usbc/usbc_pd_policy.c b/common/usbc/usbc_pd_policy.c
deleted file mode 100644
index 6a06d4014f..0000000000
--- a/common/usbc/usbc_pd_policy.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/* Copyright 2021 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.
- */
-
-#include "console.h"
-#include "ec_commands.h"
-#include "usb_pe_sm.h"
-#include "usb_tc_sm.h"
-
-/*
- * TODO(b:159715784): Implement a more robust solution
- * to managing PD Policies.
- */
-
-/*
- * Default Port Discovery DR Swap Policy.
- *
- * 1) If dr_swap_to_dfp_flag == true and port data role is UFP,
- * transition to pe_drs_send_swap
- */
-__overridable bool port_discovery_dr_swap_policy(int port,
- enum pd_data_role dr, bool dr_swap_flag)
-{
- if (dr_swap_flag && dr == PD_ROLE_UFP)
- return true;
-
- /* Do not perform a DR swap */
- return false;
-}
-
-/*
- * Default Port Discovery VCONN Swap Policy.
- *
- * 1) If vconn_swap_to_on_flag == true, and vconn is currently off,
- * 2) Sourcing VCONN is possible
- * then transition to pe_vcs_send_swap
- */
-__overridable bool port_discovery_vconn_swap_policy(int port,
- bool vconn_swap_flag)
-{
- if (IS_ENABLED(CONFIG_USBC_VCONN) && vconn_swap_flag &&
- !tc_is_vconn_src(port) && tc_check_vconn_swap(port))
- return true;
-
- /* Do not perform a VCONN swap */
- return false;
-}
diff --git a/common/usbc/usbc_task.c b/common/usbc/usbc_task.c
deleted file mode 100644
index 09be36cd5e..0000000000
--- a/common/usbc/usbc_task.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/* Copyright 2019 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.
- */
-
-#include "battery.h"
-#include "battery_smart.h"
-#include "board.h"
-#include "charge_manager.h"
-#include "charge_state.h"
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "cros_version.h"
-#include "ec_commands.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "registers.h"
-#include "system.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-#include "usb_charge.h"
-#include "usb_mux.h"
-#include "usb_pd.h"
-#include "usb_pd_timer.h"
-#include "usb_prl_sm.h"
-#include "tcpm/tcpm.h"
-#include "usb_pe_sm.h"
-#include "usb_prl_sm.h"
-#include "usb_sm.h"
-#include "usb_tc_sm.h"
-#include "usbc_ppc.h"
-
-#define USBC_EVENT_TIMEOUT (5 * MSEC)
-#define USBC_MIN_EVENT_TIMEOUT (1 * MSEC)
-
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-
-/*
- * If CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT is not defined then
- * _GPIO_CCD_MODE_ODL is not needed. Declare as extern so IS_ENABLED will work.
- */
-#ifndef CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT
-extern int _GPIO_CCD_MODE_ODL;
-#else
-#define _GPIO_CCD_MODE_ODL GPIO_CCD_MODE_ODL
-#endif /* CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT */
-
-static uint8_t paused[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-void tc_pause_event_loop(int port)
-{
- paused[port] = 1;
-}
-
-bool tc_event_loop_is_paused(int port)
-{
- return paused[port];
-}
-
-void tc_start_event_loop(int port)
-{
- /*
- * Only generate TASK_EVENT_WAKE event if state
- * machine is transitioning to un-paused
- */
- if (paused[port]) {
- paused[port] = 0;
- task_set_event(PD_PORT_TO_TASK_ID(port), TASK_EVENT_WAKE);
- }
-}
-
-static void pd_task_init(int port)
-{
- if (IS_ENABLED(CONFIG_USB_TYPEC_SM))
- tc_state_init(port);
- paused[port] = 0;
-
- /*
- * Since most boards configure the TCPC interrupt as edge
- * and it is possible that the interrupt line was asserted between init
- * and calling set_state, we need to process any pending interrupts now.
- * Otherwise future interrupts will never fire because another edge
- * never happens. Note this needs to happen after set_state() is called.
- */
- if (IS_ENABLED(CONFIG_HAS_TASK_PD_INT))
- schedule_deferred_pd_interrupt(port);
-
- /*
- * GPIO_CCD_MODE_ODL must be initialized with GPIO_ODR_HIGH
- * when CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT is enabled
- */
- if (IS_ENABLED(CONFIG_ASSERT_CCD_MODE_ON_DTS_CONNECT))
- ASSERT(gpio_get_default_flags(_GPIO_CCD_MODE_ODL) &
- GPIO_ODR_HIGH);
-}
-
-static int pd_task_timeout(int port)
-{
- int timeout;
-
- if (paused[port])
- timeout = -1;
- else {
- timeout = pd_timer_next_expiration(port);
- if (timeout < 0 || timeout > USBC_EVENT_TIMEOUT)
- timeout = USBC_EVENT_TIMEOUT;
- else if (timeout < USBC_MIN_EVENT_TIMEOUT)
- timeout = USBC_MIN_EVENT_TIMEOUT;
- }
- return timeout;
-}
-
-static bool pd_task_loop(int port)
-{
- /* wait for next event/packet or timeout expiration */
- const uint32_t evt = task_wait_event(pd_task_timeout(port));
-
- /* Manage expired PD Timers on timeouts */
- if (evt & TASK_EVENT_TIMER)
- pd_timer_manage_expired(port);
-
- /*
- * Re-use TASK_EVENT_RESET_DONE in tests to restart the USB task
- * if this code is running in a unit test.
- */
- if (IS_ENABLED(TEST_BUILD) && (evt & TASK_EVENT_RESET_DONE))
- return false;
-
- /* handle events that affect the state machine as a whole */
- if (IS_ENABLED(CONFIG_USB_TYPEC_SM))
- tc_event_check(port, evt);
-
- /*
- * run port controller task to check CC and/or read incoming
- * messages
- */
- if (IS_ENABLED(CONFIG_USB_PD_TCPC))
- tcpc_run(port, evt);
-
- /* Run policy engine state machine */
- if (IS_ENABLED(CONFIG_USB_PE_SM))
- pe_run(port, evt, tc_get_pd_enabled(port));
-
- /* Run protocol state machine */
- if (IS_ENABLED(CONFIG_USB_PRL_SM) || IS_ENABLED(CONFIG_TEST_USB_PE_SM))
- prl_run(port, evt, tc_get_pd_enabled(port));
-
- /* Run TypeC state machine */
- if (IS_ENABLED(CONFIG_USB_TYPEC_SM))
- tc_run(port);
-
- return true;
-}
-
-void pd_task(void *u)
-{
- int port = TASK_ID_TO_PD_PORT(task_get_current());
-
- /*
- * If port does not exist, return
- */
- if (port >= board_get_usb_pd_port_count())
- return;
-
- while (1) {
- pd_timer_init(port);
- pd_task_init(port);
-
- /* As long as pd_task_loop returns true, keep running the loop.
- * pd_task_loop returns false when the code needs to re-init
- * the task, so once the code breaks out of the inner while
- * loop, the re-init code at the top of the outer while loop
- * will run.
- */
- while (pd_task_loop(port))
- continue;
- }
-}
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);
- }
-}
diff --git a/common/usbc_ocp.c b/common/usbc_ocp.c
deleted file mode 100644
index e20cf9f1f8..0000000000
--- a/common/usbc_ocp.c
+++ /dev/null
@@ -1,131 +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.
- */
-
-/* USB-C Overcurrent Protection Common Code */
-
-#include "atomic.h"
-#include "common.h"
-#include "console.h"
-#include "hooks.h"
-#include "timer.h"
-#include "usb_pd.h"
-#include "usbc_ocp.h"
-#include "util.h"
-
-#ifndef TEST_BUILD
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#else
-#define CPRINTF(args...)
-#define CPRINTS(args...)
-#endif
-
-/*
- * Number of times a port may overcurrent before we latch off the port until a
- * physical disconnect is detected.
- */
-#define OCP_CNT_THRESH 3
-
-/*
- * Number of seconds until a latched-off port is re-enabled for sourcing after
- * detecting a physical disconnect.
- */
-#define OCP_COOLDOWN_DELAY_US (2 * SECOND)
-
-/*
- * A per-port table that indicates how many VBUS overcurrent events have
- * occurred. This table is cleared after detecting a physical disconnect of the
- * sink.
- */
-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 void clear_oc_tbl(void)
-{
- int port;
-
- for (port = 0; port < board_get_usb_pd_port_count(); port++)
- /*
- * Only clear the table if the port partner is no longer
- * attached after debouncing.
- */
- if ((!(BIT(port) & snk_connected_ports)) &&
- oc_event_cnt_tbl[port]) {
- oc_event_cnt_tbl[port] = 0;
- CPRINTS("C%d: OC events cleared", port);
- }
-}
-DECLARE_DEFERRED(clear_oc_tbl);
-
-int usbc_ocp_add_event(int port)
-{
- if ((port < 0) || (port >= board_get_usb_pd_port_count())) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- oc_event_cnt_tbl[port]++;
-
- /* The port overcurrented, so don't clear it's OC events. */
- atomic_clear_bits(&snk_connected_ports, 1 << port);
-
- if (oc_event_cnt_tbl[port] >= OCP_CNT_THRESH)
- CPRINTS("C%d: OC event limit reached! "
- "Source path disabled until physical disconnect.",
- port);
- return EC_SUCCESS;
-}
-
-
-int usbc_ocp_clear_event_counter(int port)
-{
- if ((port < 0) || (port >= board_get_usb_pd_port_count())) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- /*
- * If we are clearing our event table in quick succession, we may be in
- * an overcurrent loop where we are also detecting a disconnect on the
- * CC pins. Therefore, let's not clear it just yet and the let the
- * limit be reached. This way, we won't send the hard reset and
- * actually detect the physical disconnect.
- */
- if (oc_event_cnt_tbl[port]) {
- hook_call_deferred(&clear_oc_tbl_data,
- OCP_COOLDOWN_DELAY_US);
- }
- return EC_SUCCESS;
-}
-
-int usbc_ocp_is_port_latched_off(int port)
-{
- if ((port < 0) || (port >= board_get_usb_pd_port_count())) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return 0;
- }
-
- return oc_event_cnt_tbl[port] >= OCP_CNT_THRESH;
-}
-
-void usbc_ocp_snk_is_connected(int port, bool connected)
-{
- if ((port < 0) || (port >= board_get_usb_pd_port_count())) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return;
- }
-
- if (connected)
- atomic_or(&snk_connected_ports, 1 << port);
- else
- atomic_clear_bits(&snk_connected_ports, 1 << port);
-}
-
-__overridable void board_overcurrent_event(int port, int is_overcurrented)
-{
- /* Do nothing by default. Boards with overcurrent GPIOs may override */
-}
diff --git a/common/usbc_ppc.c b/common/usbc_ppc.c
deleted file mode 100644
index 0281ceaf64..0000000000
--- a/common/usbc_ppc.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/* Copyright 2017 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.
- */
-
-/* USB-C Power Path Controller Common Code */
-
-#include "atomic.h"
-#include "common.h"
-#include "console.h"
-#include "hooks.h"
-#include "timer.h"
-#include "usb_pd.h"
-#include "usbc_ppc.h"
-#include "util.h"
-
-#ifndef TEST_BUILD
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-#else
-#define CPRINTF(args...)
-#define CPRINTS(args...)
-#endif
-
-int ppc_prints(const char *string, int port)
-{
-#ifndef TEST_BUILD
- return CPRINTS("ppc p%d %s", port, string);
-#else
- return 0;
-#endif
-}
-
-int ppc_err_prints(const char *string, int port, int error)
-{
-#ifndef TEST_BUILD
- return CPRINTS("ppc p%d %s (%d)", port, string, error);
-#else
- return 0;
-#endif
-}
-
-/* Simple wrappers to dispatch to the drivers. */
-
-int ppc_init(int port)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->init) {
- rv = ppc->drv->init(port);
- if (rv)
- ppc_err_prints("init failed!", port, rv);
- else
- ppc_prints("init'd.", port);
- }
-
- return rv;
-}
-
-int ppc_is_sourcing_vbus(int port)
-{
- int rv = 0;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return 0;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->is_sourcing_vbus)
- rv = ppc->drv->is_sourcing_vbus(port);
-
- return rv;
-}
-
-#ifdef CONFIG_USBC_PPC_POLARITY
-int ppc_set_polarity(int port, int polarity)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->set_polarity)
- rv = ppc->drv->set_polarity(port, polarity);
-
- return rv;
-}
-#endif
-
-int ppc_set_vbus_source_current_limit(int port, enum tcpc_rp_value rp)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->set_vbus_source_current_limit)
- rv = ppc->drv->set_vbus_source_current_limit(port, rp);
-
- return rv;
-}
-
-int ppc_discharge_vbus(int port, int enable)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->discharge_vbus)
- rv = ppc->drv->discharge_vbus(port, enable);
-
- return rv;
-}
-
-#ifdef CONFIG_USBC_PPC_SBU
-int ppc_set_sbu(int port, int enable)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->set_sbu)
- rv = ppc->drv->set_sbu(port, enable);
-
- return rv;
-}
-#endif /* defined(CONFIG_USBC_PPC_SBU) */
-
-#ifdef CONFIG_USBC_PPC_VCONN
-int ppc_set_vconn(int port, int enable)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->set_vconn)
- rv = ppc->drv->set_vconn(port, enable);
-
- return rv;
-}
-#endif
-
-int ppc_dev_is_connected(int port, enum ppc_device_role dev)
-{
- int rv = EC_SUCCESS;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->dev_is_connected)
- rv = ppc->drv->dev_is_connected(port, dev);
-
- return rv;
-}
-
-int ppc_vbus_sink_enable(int port, int enable)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->vbus_sink_enable)
- rv = ppc->drv->vbus_sink_enable(port, enable);
-
- return rv;
-}
-
-int ppc_enter_low_power_mode(int port)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->enter_low_power_mode)
- rv = ppc->drv->enter_low_power_mode(port);
-
- return rv;
-}
-
-int ppc_vbus_source_enable(int port, int enable)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->vbus_source_enable)
- rv = ppc->drv->vbus_source_enable(port, enable);
-
- return rv;
-}
-
-#ifdef CONFIG_USB_PD_FRS_PPC
-int ppc_set_frs_enable(int port, int enable)
-{
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
-
- if (ppc->drv->set_frs_enable)
- rv = ppc->drv->set_frs_enable(port,enable);
-
- return rv;
-}
-#endif /* defined(CONFIG_USB_PD_FRS_PPC) */
-
-#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC
-int ppc_is_vbus_present(int port)
-{
- int rv = 0;
- const struct ppc_config_t *ppc;
-
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return 0;
- }
-
- ppc = &ppc_chips[port];
-
- if (ppc->drv->is_vbus_present)
- rv = ppc->drv->is_vbus_present(port);
-
- return rv;
-}
-#endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */
-
-#ifdef CONFIG_CMD_PPC_DUMP
-static int command_ppc_dump(int argc, char **argv)
-{
- int port;
- int rv = EC_ERROR_UNIMPLEMENTED;
- const struct ppc_config_t *ppc;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- port = atoi(argv[1]);
- if ((port < 0) || (port >= ppc_cnt)) {
- CPRINTS("%s(%d) Invalid port!", __func__, port);
- return EC_ERROR_INVAL;
- }
-
- ppc = &ppc_chips[port];
- if (ppc->drv->reg_dump)
- rv = ppc->drv->reg_dump(port);
-
- return rv;
-}
-DECLARE_CONSOLE_COMMAND(ppc_dump, command_ppc_dump, "<Type-C port>",
- "dump the PPC regs");
-#endif /* defined(CONFIG_CMD_PPC_DUMP) */
diff --git a/common/vboot/common.c b/common/vboot/common.c
deleted file mode 100644
index 39f8c193c7..0000000000
--- a/common/vboot/common.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Copyright 2017 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.
- */
-
-#include "common.h"
-#include "console.h"
-#include "rsa.h"
-#include "sha256.h"
-#include "shared_mem.h"
-#include "vboot.h"
-
-#define CPRINTS(format, args...) cprints(CC_VBOOT, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_VBOOT, format, ## args)
-
-int vboot_is_padding_valid(const uint8_t *data, uint32_t start, uint32_t end)
-{
- const uint32_t *data32 = (const uint32_t *)data;
- int i;
-
- if (start > end)
- return EC_ERROR_INVAL;
-
- if (start % 4 || end % 4)
- return EC_ERROR_INVAL;
-
- for (i = start / 4; i < end / 4; i++) {
- if (data32[i] != 0xffffffff)
- return EC_ERROR_INVAL;
- }
-
- return EC_SUCCESS;
-}
-
-int vboot_verify(const uint8_t *data, int len,
- const struct rsa_public_key *key, const uint8_t *sig)
-{
- struct sha256_ctx ctx;
- uint8_t *hash;
- uint32_t *workbuf;
- int err = EC_SUCCESS;
-
- if (SHARED_MEM_ACQUIRE_CHECK(3 * RSANUMBYTES, (char **)&workbuf))
- return EC_ERROR_MEMORY_ALLOCATION;
-
- /* Compute hash of the RW firmware */
- SHA256_init(&ctx);
- SHA256_update(&ctx, data, len);
- hash = SHA256_final(&ctx);
-
- /* Verify the data */
- if (rsa_verify(key, sig, hash, workbuf) != 1)
- err = EC_ERROR_VBOOT_DATA_VERIFY;
-
- shared_mem_release(workbuf);
-
- return err;
-}
diff --git a/common/vboot/efs2.c b/common/vboot/efs2.c
deleted file mode 100644
index e5c3b64f04..0000000000
--- a/common/vboot/efs2.c
+++ /dev/null
@@ -1,352 +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.
- */
-
-/*
- * Early Firmware Selection ver.2.
- *
- * Verify and jump to a RW image. Register boot mode to Cr50.
- */
-
-#include "battery.h"
-#include "chipset.h"
-#include "clock.h"
-#include "compile_time_macros.h"
-#include "console.h"
-#include "crc8.h"
-#include "flash.h"
-#include "hooks.h"
-#include "sha256.h"
-#include "system.h"
-#include "task.h"
-#include "usb_pd.h"
-#include "uart.h"
-#include "vboot.h"
-#include "vboot_hash.h"
-
-#define CPRINTS(format, args...) cprints(CC_VBOOT,"VB " format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_VBOOT,"VB " format, ## args)
-
-static const char *boot_mode_to_string(uint8_t mode)
-{
- static const char *boot_mode_str[] = {
- [BOOT_MODE_NORMAL] = "NORMAL",
- [BOOT_MODE_NO_BOOT] = "NO_BOOT",
- };
- if (mode < ARRAY_SIZE(boot_mode_str))
- return boot_mode_str[mode];
- return "UNDEF";
-}
-
-/*
- * Check whether the session has successfully ended or not. ERR_TIMEOUT is
- * excluded because it's an internal error produced by EC itself.
- */
-static bool is_valid_cr50_response(enum cr50_comm_err code)
-{
- return code != CR50_COMM_ERR_TIMEOUT
- && (code >> 8) == CR50_COMM_ERR_PREFIX;
-}
-
-__overridable void board_enable_packet_mode(bool enable)
-{
- /*
- * This can be done by set_flags(INPUT|PULL_UP). We don't need it now
- * because Cr50 never initiates communication.
- */
- gpio_set_level(GPIO_PACKET_MODE_EN, enable ? 1 : 0);
-}
-
-static enum cr50_comm_err send_to_cr50(const uint8_t *data, size_t size)
-{
- timestamp_t until;
- int i, timeout = 0;
- uint32_t lock_key;
- struct cr50_comm_response res = {};
-
- /* This will wake up (if it's sleeping) and interrupt Cr50. */
- board_enable_packet_mode(true);
-
- uart_flush_output();
- uart_clear_input();
-
- if (uart_shell_stop()) {
- /* Failed to stop the shell. */
- board_enable_packet_mode(false);
- return CR50_COMM_ERR_UNKNOWN;
- }
-
- /*
- * Send packet. No traffic control, assuming Cr50 consumes stream much
- * faster. TX buffer shouldn't overflow because it's cleared above and
- * much bigger than the max packet size.
- *
- * Disable interrupts so that the data frame will be stored in the Tx
- * buffer in one piece.
- */
- lock_key = irq_lock();
- uart_put_raw(data, size);
- irq_unlock(lock_key);
-
- uart_flush_output();
-
- until.val = get_time().val + CR50_COMM_TIMEOUT;
-
- /*
- * Make sure console task won't steal the response in case we exchange
- * packets after tasks start.
- */
-#ifndef CONFIG_ZEPHYR
- if (task_start_called())
- task_disable_task(TASK_ID_CONSOLE);
-#endif /* !CONFIG_ZEPHYR */
-
- /* Wait for response from Cr50 */
- for (i = 0; i < sizeof(res); i++) {
- while (!timeout) {
- int c = uart_getc();
- if (c != -1) {
- res.error = res.error | c << (i*8);
- break;
- }
- msleep(1);
- timeout = timestamp_expired(until, NULL);
- }
- }
-
- uart_shell_start();
-#ifndef CONFIG_ZEPHYR
- if (task_start_called())
- task_enable_task(TASK_ID_CONSOLE);
-#endif /* CONFIG_ZEPHYR */
-
- /* Exit packet mode */
- board_enable_packet_mode(false);
-
- CPRINTS("Received 0x%04x", res.error);
-
- if (timeout) {
- CPRINTS("Timeout");
- return CR50_COMM_ERR_TIMEOUT;
- }
-
- return res.error;
-}
-
-static enum cr50_comm_err cmd_to_cr50(enum cr50_comm_cmd cmd,
- const uint8_t *data, size_t size)
-{
- /*
- * This is on the stack instead of .bss because vboot_main currently is
- * called only once (from main). Keeping the space unused in .bss would
- * be wasteful.
- */
- struct {
- uint8_t preamble[CR50_UART_RX_BUFFER_SIZE];
- uint8_t packet[CR50_COMM_MAX_REQUEST_SIZE];
- } __packed s;
- struct cr50_comm_request *p = (struct cr50_comm_request *)s.packet;
- int retry = CR50_COMM_MAX_RETRY;
- enum cr50_comm_err rv;
-
- /* compose a frame = preamble + packet */
- memset(s.preamble, CR50_COMM_PREAMBLE, sizeof(s.preamble));
- p->magic = CR50_PACKET_MAGIC;
- p->struct_version = CR50_COMM_PACKET_VERSION;
- p->type = cmd;
- p->size = size;
- memcpy(p->data, data, size);
- p->crc = cros_crc8((uint8_t *)&p->type,
- sizeof(p->type) + sizeof(p->size) + size);
-
- do {
- rv = send_to_cr50((uint8_t *)&s,
- sizeof(s.preamble) + sizeof(*p) + p->size);
- if (is_valid_cr50_response(rv))
- break;
- msleep(5);
- } while (--retry);
-
- return rv;
-}
-
-static enum cr50_comm_err verify_hash(void)
-{
- const uint8_t *hash;
- int rv;
-
- /* Wake up Cr50 beforehand in case it's asleep. */
- board_enable_packet_mode(true);
- CPRINTS("Ping Cr50");
- msleep(1);
- board_enable_packet_mode(false);
-
- rv = vboot_get_rw_hash(&hash);
- if (rv)
- return rv;
-
- CPRINTS("Verifying hash");
- return cmd_to_cr50(CR50_COMM_CMD_VERIFY_HASH, hash, SHA256_DIGEST_SIZE);
-}
-
-static enum cr50_comm_err set_boot_mode(uint8_t mode)
-{
- enum cr50_comm_err rv;
-
- CPRINTS("Setting boot mode to %s(%d)", boot_mode_to_string(mode), mode);
- rv = cmd_to_cr50(CR50_COMM_CMD_SET_BOOT_MODE,
- &mode, sizeof(enum boot_mode));
- if (rv != CR50_COMM_SUCCESS)
- CPRINTS("Failed to set boot mode");
- return rv;
-}
-
-static bool pd_comm_enabled;
-
-static void enable_pd(void)
-{
- CPRINTS("Enable USB-PD");
- pd_comm_enabled = true;
-}
-
-bool vboot_allow_usb_pd(void)
-{
- return pd_comm_enabled;
-}
-
-__overridable void show_critical_error(void)
-{
- CPRINTS("%s", __func__);
-}
-
-static void verify_and_jump(void)
-{
- enum cr50_comm_err rv = verify_hash();
-
- switch (rv) {
- case CR50_COMM_ERR_BAD_PAYLOAD:
- /* Cr50 should have set NO_BOOT. */
- CPRINTS("Hash mismatch");
- enable_pd();
- break;
- case CR50_COMM_SUCCESS:
- system_set_reset_flags(EC_RESET_FLAG_EFS);
- rv = system_run_image_copy(EC_IMAGE_RW);
- CPRINTS("Failed to jump (0x%x)", rv);
- system_clear_reset_flags(EC_RESET_FLAG_EFS);
- show_critical_error();
- break;
- default:
- CPRINTS("Failed to verify RW (0x%x)", rv);
- show_critical_error();
- }
-}
-
-__overridable void show_power_shortage(void)
-{
- CPRINTS("%s", __func__);
-}
-
-static bool is_battery_ready(void)
-{
- /* TODO: Add battery check (https://crbug.com/1045216) */
- return true;
-}
-
-void vboot_main(void)
-{
- CPRINTS("Main");
-
- if (system_is_in_rw()) {
- /*
- * We come here and immediately return. LED shows power shortage
- * but it will be immediately corrected if the adapter can
- * provide enough power.
- */
- CPRINTS("Already in RW");
- show_power_shortage();
- return;
- }
-
- if (system_is_manual_recovery() ||
- (system_get_reset_flags() & EC_RESET_FLAG_STAY_IN_RO)) {
- if (system_is_manual_recovery())
- CPRINTS("In recovery mode");
- if (!IS_ENABLED(CONFIG_BATTERY)
- && !IS_ENABLED(HAS_TASK_KEYSCAN)) {
- /*
- * For Chromeboxes, we relax security by allowing PD in
- * RO. Attackers don't gain meaningful advantage on
- * built-in-keyboard-less systems.
- *
- * Alternatively, we can use NO_BOOT to show a firmware
- * screen, strictly requiring BJ adapter and keeping PD
- * disabled.
- */
- enable_pd();
- return;
- }
-
- /*
- * If battery is drained or bad, we will boot in NO_BOOT mode to
- * inform the user of the problem.
- */
- if (!is_battery_ready()) {
- CPRINTS("Battery not ready or bad");
- if (set_boot_mode(BOOT_MODE_NO_BOOT) ==
- CR50_COMM_SUCCESS)
- enable_pd();
- }
-
- /* We'll enter recovery mode immediately, later, or never. */
- return;
- }
-
- verify_and_jump();
-
- /*
- * EFS failed. EC-RO may be able to boot AP if:
- *
- * - Battery is charged or
- * - AC adapter supply in RO >= Boot threshold or
- * - BJ adapter is plugged.
- *
- * Once AP boots, software sync will fix the mismatch. If that's the
- * reason of the failure, we won't come back here next time.
- */
- CPRINTS("Exit");
-}
-
-void hook_shutdown(void)
-{
- CPRINTS("%s", __func__);
-
- /*
- * We filter the cases which can be interfered with if we execute
- * system_reset in HOOK_CHIPSET_SHUTDOWN context. Most cases are
- * filtered out by system_is_in_rw (e.g. system_common_shutdown,
- * check_pending_cutoff).
- */
- if (system_is_in_rw())
- return;
-
- /*
- * We can't reset here because it'll completely tear down the power
- * and disturb the PCH's power sequence. We instead sysjump.
- *
- * Note that this does not reduce the security. Even if it's hijacked in
- * NO_BOOT mode, an RO still needs to go through a cold reset to clear
- * NO_BOOT flag since Cr50 rejects to switch from NO_BOOT to NORMAL.
- * If a spoofed matching hash is passed to Cr50, Cr50 would reset EC.
- */
- system_set_reset_flags(EC_RESET_FLAG_AP_IDLE);
- verify_and_jump();
-}
-/*
- * There can be hooks which are needed to set external chips to a certain state
- * in S5. If the initial state (i.e. AP_OFF state) is different from what those
- * hooks realize, they need to be considered. This hook runs last (i.e.
- * HOOK_PRIO_LAST) to make our landing on S5 as mild as possible.
- */
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN_COMPLETE, hook_shutdown, HOOK_PRIO_LAST);
diff --git a/common/vboot/vb21_lib.c b/common/vboot/vb21_lib.c
deleted file mode 100644
index 4e215c14e5..0000000000
--- a/common/vboot/vb21_lib.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/* Copyright 2017 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.
- */
-
-/*
- * Common utility APIs for vboot 2.1
- */
-
-#include "common.h"
-#include "host_command.h"
-#include "rsa.h"
-#include "rwsig.h"
-#include "system.h"
-#include "vb21_struct.h"
-#include "vboot.h"
-
-int vb21_is_packed_key_valid(const struct vb21_packed_key *key)
-{
- if (key->c.magic != VB21_MAGIC_PACKED_KEY)
- return EC_ERROR_VBOOT_KEY_MAGIC;
- if (key->key_size != sizeof(struct rsa_public_key))
- return EC_ERROR_VBOOT_KEY_SIZE;
- return EC_SUCCESS;
-}
-
-int vb21_is_signature_valid(const struct vb21_signature *sig,
- const struct vb21_packed_key *key)
-{
- if (sig->c.magic != VB21_MAGIC_SIGNATURE)
- return EC_ERROR_VBOOT_SIG_MAGIC;
- if (sig->sig_size != RSANUMBYTES)
- return EC_ERROR_VBOOT_SIG_SIZE;
- if (key->sig_alg != sig->sig_alg)
- return EC_ERROR_VBOOT_SIG_ALGORITHM;
- if (key->hash_alg != sig->hash_alg)
- return EC_ERROR_VBOOT_HASH_ALGORITHM;
- /* Validity check signature offset and data size. */
- if (sig->sig_offset < sizeof(*sig))
- return EC_ERROR_VBOOT_SIG_OFFSET;
- if (sig->sig_offset + RSANUMBYTES > CONFIG_RW_SIG_SIZE)
- return EC_ERROR_VBOOT_SIG_OFFSET;
- if (sig->data_size > CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE)
- return EC_ERROR_VBOOT_DATA_SIZE;
- return EC_SUCCESS;
-}
-
-const struct vb21_packed_key *vb21_get_packed_key(void)
-{
- return (const struct vb21_packed_key *)(CONFIG_RO_PUBKEY_ADDR);
-}
-
-static void read_rwsig_info(struct ec_response_rwsig_info *r)
-{
-
- const struct vb21_packed_key *vb21_key;
- int rv;
-
- vb21_key = vb21_get_packed_key();
-
- r->sig_alg = vb21_key->sig_alg;
- r->hash_alg = vb21_key->hash_alg;
- r->key_version = vb21_key->key_version;
- { BUILD_ASSERT(sizeof(r->key_id) == sizeof(vb21_key->id),
- "key ID sizes must match"); }
- { BUILD_ASSERT(sizeof(vb21_key->id) == sizeof(vb21_key->id.raw),
- "key ID sizes must match"); }
- memcpy(r->key_id, vb21_key->id.raw, sizeof(r->key_id));
-
- rv = vb21_is_packed_key_valid(vb21_key);
- r->key_is_valid = (rv == EC_SUCCESS);
-}
-
-static int command_rwsig_info(int argc, char **argv)
-{
- int i;
- struct ec_response_rwsig_info r;
-
- read_rwsig_info(&r);
-
- ccprintf("sig_alg: %d\n", r.sig_alg);
- ccprintf("key_version: %d\n", r.key_version);
- ccprintf("hash_alg: %d\n", r.hash_alg);
- ccprintf("key_is_valid: %d\n", r.key_is_valid);
-
- ccprintf("key_id: ");
- for (i = 0; i < sizeof(r.key_id); i++)
- ccprintf("%x", r.key_id[i]);
- ccprintf("\n");
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(rwsiginfo, command_rwsig_info, NULL,
- "Display rwsig info on console.");
-
-static enum ec_status
-host_command_rwsig_info(struct host_cmd_handler_args *args)
-{
- struct ec_response_rwsig_info *r = args->response;
-
- read_rwsig_info(r);
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-
-DECLARE_HOST_COMMAND(EC_CMD_RWSIG_INFO, host_command_rwsig_info,
- EC_VER_MASK(EC_VER_RWSIG_INFO));
diff --git a/common/vboot/vboot.c b/common/vboot/vboot.c
deleted file mode 100644
index 910156335d..0000000000
--- a/common/vboot/vboot.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/* Copyright 2017 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.
- */
-
-/*
- * Verify and jump to a RW image if power supply is not sufficient.
- */
-
-#include "battery.h"
-#include "charge_manager.h"
-#include "chipset.h"
-#include "clock.h"
-#include "console.h"
-#include "flash.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "rsa.h"
-#include "rwsig.h"
-#include "stdbool.h"
-#include "sha256.h"
-#include "shared_mem.h"
-#include "system.h"
-#include "usb_pd.h"
-#include "vboot.h"
-#include "vb21_struct.h"
-
-#define CPRINTS(format, args...) cprints(CC_VBOOT,"VB " format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_VBOOT,"VB " format, ## args)
-
-static int has_matrix_keyboard(void)
-{
- return 0;
-}
-
-static int verify_slot(enum ec_image slot)
-{
- const struct vb21_packed_key *vb21_key;
- const struct vb21_signature *vb21_sig;
- const struct rsa_public_key *key;
- const uint8_t *sig;
- const uint8_t *data;
- int len;
- int rv;
-
- CPRINTS("Verifying %s", ec_image_to_string(slot));
-
- vb21_key = (const struct vb21_packed_key *)(
- CONFIG_MAPPED_STORAGE_BASE +
- CONFIG_EC_PROTECTED_STORAGE_OFF +
- CONFIG_RO_PUBKEY_STORAGE_OFF);
- rv = vb21_is_packed_key_valid(vb21_key);
- if (rv) {
- CPRINTS("Invalid key (%d)", rv);
- return EC_ERROR_VBOOT_KEY;
- }
- key = (const struct rsa_public_key *)
- ((const uint8_t *)vb21_key + vb21_key->key_offset);
-
- if (slot == EC_IMAGE_RW_A) {
- data = (const uint8_t *)(CONFIG_MAPPED_STORAGE_BASE +
- CONFIG_EC_WRITABLE_STORAGE_OFF +
- CONFIG_RW_A_STORAGE_OFF);
- vb21_sig = (const struct vb21_signature *)(
- CONFIG_MAPPED_STORAGE_BASE +
- CONFIG_EC_WRITABLE_STORAGE_OFF +
- CONFIG_RW_A_SIGN_STORAGE_OFF);
- } else {
- data = (const uint8_t *)(CONFIG_MAPPED_STORAGE_BASE +
- CONFIG_EC_WRITABLE_STORAGE_OFF +
- CONFIG_RW_B_STORAGE_OFF);
- vb21_sig = (const struct vb21_signature *)(
- CONFIG_MAPPED_STORAGE_BASE +
- CONFIG_EC_WRITABLE_STORAGE_OFF +
- CONFIG_RW_B_SIGN_STORAGE_OFF);
- }
-
- rv = vb21_is_signature_valid(vb21_sig, vb21_key);
- if (rv) {
- CPRINTS("Invalid signature (%d)", rv);
- return EC_ERROR_INVAL;
- }
- sig = (const uint8_t *)vb21_sig + vb21_sig->sig_offset;
- len = vb21_sig->data_size;
-
- if (vboot_is_padding_valid(data, len,
- CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE)) {
- CPRINTS("Invalid padding");
- return EC_ERROR_INVAL;
- }
-
- rv = vboot_verify(data, len, key, sig);
- if (rv) {
- CPRINTS("Invalid data (%d)", rv);
- return EC_ERROR_INVAL;
- }
-
- CPRINTS("Verified %s", ec_image_to_string(slot));
-
- return EC_SUCCESS;
-}
-
-static enum ec_status hc_verify_slot(struct host_cmd_handler_args *args)
-{
- const struct ec_params_efs_verify *p = args->params;
- enum ec_image slot;
-
- switch (p->region) {
- case EC_FLASH_REGION_ACTIVE:
- slot = system_get_active_copy();
- break;
- case EC_FLASH_REGION_UPDATE:
- slot = system_get_update_copy();
- break;
- default:
- return EC_RES_INVALID_PARAM;
- }
- return verify_slot(slot) ? EC_RES_ERROR : EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_EFS_VERIFY, hc_verify_slot, EC_VER_MASK(0));
-
-static int verify_and_jump(void)
-{
- enum ec_image slot;
- int rv;
-
- /* 1. Decide which slot to try */
- slot = system_get_active_copy();
-
- /* 2. Verify the slot */
- rv = verify_slot(slot);
- if (rv) {
- if (rv == EC_ERROR_VBOOT_KEY)
- /* Key error. The other slot isn't worth trying. */
- return rv;
- slot = system_get_update_copy();
- /* TODO(chromium:767050): Skip reading key again. */
- rv = verify_slot(slot);
- if (rv)
- /* Both slots failed */
- return rv;
-
- /* Proceed with the other slot. If this slot isn't expected, AP
- * will catch it and request recovery after a few attempts. */
- if (system_set_active_copy(slot))
- CPRINTS("Failed to activate %s",
- ec_image_to_string(slot));
- }
-
- /* 3. Jump (and reboot) */
- rv = system_run_image_copy(slot);
- CPRINTS("Failed to jump (%d)", rv);
-
- return rv;
-}
-
-/* Request more power: charging battery or more powerful AC adapter */
-__overridable void show_power_shortage(void)
-{
- CPRINTS("%s", __func__);
-}
-
-__overridable void show_critical_error(void)
-{
- CPRINTS("%s", __func__);
-}
-
-static bool pd_comm_enabled;
-
-bool vboot_allow_usb_pd(void)
-{
- return pd_comm_enabled;
-}
-
-void vboot_main(void)
-{
- CPRINTS("Main");
-
- if (system_is_in_rw()) {
- /*
- * We come here and immediately return. LED shows power shortage
- * but it will be immediately corrected if the adapter can
- * provide enough power.
- */
- CPRINTS("Already in RW. Wait for power...");
- show_power_shortage();
- return;
- }
-
- if (!(crec_flash_get_protect() & EC_FLASH_PROTECT_GPIO_ASSERTED)) {
- /*
- * If hardware WP is disabled, PD communication is enabled.
- * We can return and wait for more power.
- * Note: If software WP is disabled, we still perform EFS even
- * though PD communication is enabled.
- */
- CPRINTS("HW-WP not asserted.");
- show_power_shortage();
- return;
- }
-
- if (system_is_manual_recovery() ||
- (system_get_reset_flags() & EC_RESET_FLAG_STAY_IN_RO)) {
- if (system_is_manual_recovery())
- CPRINTS("Manual recovery");
-
- if (battery_is_present() || has_matrix_keyboard()) {
- show_power_shortage();
- return;
- }
- /* We don't request_power because we don't want to assume all
- * devices support a non type-c charger. We open up a security
- * hole by allowing EC-RO to do PD negotiation but attackers
- * don't gain meaningful advantage on devices without a matrix
- * keyboard */
- CPRINTS("Enable PD comm");
- pd_comm_enabled = true;
- return;
- }
-
- clock_enable_module(MODULE_FAST_CPU, 1);
- /* If successful, this won't return. */
- verify_and_jump();
- clock_enable_module(MODULE_FAST_CPU, 0);
-
- /* Failed to jump. Need recovery. */
- show_critical_error();
-}
diff --git a/common/vboot_hash.c b/common/vboot_hash.c
deleted file mode 100644
index 33172e7c74..0000000000
--- a/common/vboot_hash.c
+++ /dev/null
@@ -1,498 +0,0 @@
-/* Copyright 2012 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.
- */
-
-/* Verified boot hash computing module for Chrome EC */
-
-#include "clock.h"
-#include "common.h"
-#include "console.h"
-#include "flash.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "sha256.h"
-#include "shared_mem.h"
-#include "stdbool.h"
-#include "stdint.h"
-#include "system.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-#include "watchdog.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_VBOOT, outstr)
-#define CPRINTS(format, args...) cprints(CC_VBOOT, format, ## args)
-
-struct vboot_hash_tag {
- uint8_t hash[SHA256_DIGEST_SIZE];
- uint32_t offset;
- uint32_t size;
-};
-
-#define CHUNK_SIZE 1024 /* Bytes to hash per deferred call */
-#define WORK_INTERVAL_US 100 /* Delay between deferred calls */
-
-/* Check that CHUNK_SIZE fits in shared memory. */
-SHARED_MEM_CHECK_SIZE(CHUNK_SIZE);
-
-static uint32_t data_offset;
-static uint32_t data_size;
-static uint32_t curr_pos;
-static const uint8_t *hash; /* Hash, or NULL if not valid */
-static int want_abort;
-static int in_progress;
-#define VBOOT_HASH_DEFERRED true
-#define VBOOT_HASH_BLOCKING false
-
-static struct sha256_ctx ctx;
-
-int vboot_hash_in_progress(void)
-{
- return in_progress;
-}
-
-/**
- * Abort hash currently in progress, and invalidate any completed hash.
- */
-void vboot_hash_abort(void)
-{
- if (in_progress) {
- want_abort = 1;
- } else {
- CPRINTS("hash abort");
- want_abort = 0;
- data_size = 0;
- hash = NULL;
-#ifdef CONFIG_SHA256_HW_ACCELERATE
- SHA256_abort(&ctx);
-#endif
- }
-}
-
-static void vboot_hash_next_chunk(void);
-DECLARE_DEFERRED(vboot_hash_next_chunk);
-
-#ifndef CONFIG_MAPPED_STORAGE
-
-static int read_and_hash_chunk(int offset, int size)
-{
- char *buf;
- int rv;
-
- if (size == 0)
- return EC_SUCCESS;
-
- rv = shared_mem_acquire(size, &buf);
- if (rv == EC_ERROR_BUSY) {
- /* Couldn't update hash right now; try again later */
- hook_call_deferred(&vboot_hash_next_chunk_data,
- WORK_INTERVAL_US);
- return rv;
- } else if (rv != EC_SUCCESS) {
- vboot_hash_abort();
- return rv;
- }
-
- rv = crec_flash_read(offset, size, buf);
- if (rv == EC_SUCCESS)
- SHA256_update(&ctx, (const uint8_t *)buf, size);
- else
- vboot_hash_abort();
-
- shared_mem_release(buf);
- return rv;
-}
-
-#endif
-
-#ifdef CONFIG_CONSOLE_VERBOSE
-#define SHA256_PRINT_SIZE SHA256_DIGEST_SIZE
-#else
-#define SHA256_PRINT_SIZE 4
-#endif
-
-static void hash_next_chunk(size_t size)
-{
-#ifdef CONFIG_MAPPED_STORAGE
- crec_flash_lock_mapped_storage(1);
- SHA256_update(&ctx, (const uint8_t *)
- ((uintptr_t)CONFIG_MAPPED_STORAGE_BASE +
- data_offset + curr_pos), size);
- crec_flash_lock_mapped_storage(0);
-#else
- if (read_and_hash_chunk(data_offset + curr_pos, size) != EC_SUCCESS)
- return;
-#endif
-}
-
-static void vboot_hash_all_chunks(void)
-{
- do {
- size_t size = MIN(CHUNK_SIZE, data_size - curr_pos);
- hash_next_chunk(size);
- curr_pos += size;
- } while (curr_pos < data_size);
-
- hash = SHA256_final(&ctx);
- CPRINTS("hash done %ph", HEX_BUF(hash, SHA256_PRINT_SIZE));
- in_progress = 0;
- clock_enable_module(MODULE_FAST_CPU, 0);
-
- return;
-}
-
-/**
- * Do next chunk of hashing work, if any.
- */
-static void vboot_hash_next_chunk(void)
-{
- int size;
-
- /* Handle abort */
- if (want_abort) {
- in_progress = 0;
- clock_enable_module(MODULE_FAST_CPU, 0);
- vboot_hash_abort();
- return;
- }
-
- /* Compute the next chunk of hash */
- size = MIN(CHUNK_SIZE, data_size - curr_pos);
- hash_next_chunk(size);
-
- curr_pos += size;
- if (curr_pos >= data_size) {
- /* Store the final hash */
- hash = SHA256_final(&ctx);
- CPRINTS("hash done %ph", HEX_BUF(hash, SHA256_PRINT_SIZE));
-
- in_progress = 0;
-
- clock_enable_module(MODULE_FAST_CPU, 0);
-
- /* Handle receiving abort during finalize */
- if (want_abort)
- vboot_hash_abort();
-
- return;
- }
-
- /* If we're still here, more work to do; come back later */
- hook_call_deferred(&vboot_hash_next_chunk_data, WORK_INTERVAL_US);
-}
-
-/**
- *
- * If nonce_size is non-zero, prefixes the <nonce> onto the data to be hashed.
- * Returns non-zero if error.
- */
-/**
- * Start computing a hash of <size> bytes of data at flash offset <offset>.
- *
- * @param offset start address of data on flash to compute hash for.
- * @param size size of data to compute hash for.
- * @param nonce nonce to differentiate hash.
- * @param nonce_size size of nonce.
- * @param deferred True to hash progressively through deferred calls.
- * False to hash with a blocking single call.
- * @return ec_error_list.
- */
-static int vboot_hash_start(uint32_t offset, uint32_t size,
- const uint8_t *nonce, int nonce_size, bool deferred)
-{
- /* Fail if hash computation is already in progress */
- if (in_progress)
- return EC_ERROR_BUSY;
-
- /*
- * Make sure request fits inside flash. That is, you can't use this
- * command to peek at other memory.
- */
- if (offset > CONFIG_FLASH_SIZE_BYTES ||
- size > CONFIG_FLASH_SIZE_BYTES ||
- offset + size > CONFIG_FLASH_SIZE_BYTES || nonce_size < 0) {
- return EC_ERROR_INVAL;
- }
-
- clock_enable_module(MODULE_FAST_CPU, 1);
- /* Save new hash request */
- data_offset = offset;
- data_size = size;
- curr_pos = 0;
- hash = NULL;
- want_abort = 0;
- in_progress = 1;
-
- /* Restart the hash computation */
- CPRINTS("hash start 0x%08x 0x%08x", offset, size);
- SHA256_init(&ctx);
- if (nonce_size)
- SHA256_update(&ctx, nonce, nonce_size);
-
- if (deferred)
- hook_call_deferred(&vboot_hash_next_chunk_data, 0);
- else
- vboot_hash_all_chunks();
-
- return EC_SUCCESS;
-}
-
-int vboot_hash_invalidate(int offset, int size)
-{
- /* Don't invalidate if passed an invalid region */
- if (offset < 0 || size <= 0 || offset + size < 0)
- return 0;
-
- /* Don't invalidate if hash is already invalid */
- if (!hash)
- return 0;
-
- /*
- * Always invalidate zero-size hash. No overlap if passed region is off
- * either end of hashed region.
- */
- if (data_size > 0 &&
- (offset + size <= data_offset || offset >= data_offset + data_size))
- return 0;
-
- /* Invalidate the hash */
- CPRINTS("hash invalidated 0x%08x 0x%08x", offset, size);
- vboot_hash_abort();
- return 1;
-}
-
-/*****************************************************************************/
-/* Hooks */
-
-/**
- * Returns the size of a RW copy to be hashed as expected by Softsync.
- */
-static uint32_t get_rw_size(void)
-{
-#ifdef CONFIG_VBOOT_EFS /* Only needed for EFS, which signs and verifies
- * entire RW, thus not needed for EFS2, which
- * verifies only the used image size. */
- return CONFIG_RW_SIZE;
-#else
- return system_get_image_used(EC_IMAGE_RW);
-#endif
-}
-
-static void vboot_hash_init(void)
-{
-#ifdef CONFIG_HOSTCMD_EVENTS
- /*
- * Don't auto-start hash computation if we've asked the host to enter
- * recovery mode since we probably won't need the hash. Although
- * the host is capable of clearing this host event, the host is
- * likely not even up and running yet in the case of cold boot, due to
- * the power sequencing task not having run yet.
- */
- if (!(host_get_events() &
- EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)))
-#endif
- {
- /* Start computing the hash of RW firmware */
- vboot_hash_start(flash_get_rw_offset(system_get_active_copy()),
- get_rw_size(), NULL, 0, VBOOT_HASH_DEFERRED);
- }
-}
-DECLARE_HOOK(HOOK_INIT, vboot_hash_init, HOOK_PRIO_INIT_VBOOT_HASH);
-
-int vboot_get_rw_hash(const uint8_t **dst)
-{
- int rv = vboot_hash_start(flash_get_rw_offset(system_get_active_copy()),
- get_rw_size(), NULL, 0, VBOOT_HASH_BLOCKING);
- *dst = hash;
- return rv;
-}
-
-/**
- * Returns the offset of RO or RW image if the either region is specifically
- * requested otherwise return the current hash offset.
- */
-static int get_offset(int offset)
-{
- if (offset == EC_VBOOT_HASH_OFFSET_RO)
- return CONFIG_EC_PROTECTED_STORAGE_OFF + CONFIG_RO_STORAGE_OFF;
- if (offset == EC_VBOOT_HASH_OFFSET_ACTIVE)
- return flash_get_rw_offset(system_get_active_copy());
- if (offset == EC_VBOOT_HASH_OFFSET_UPDATE)
- return flash_get_rw_offset(system_get_update_copy());
- return offset;
-}
-
-/****************************************************************************/
-/* Console commands */
-#ifdef CONFIG_CMD_HASH
-static int command_hash(int argc, char **argv)
-{
- uint32_t offset = CONFIG_EC_WRITABLE_STORAGE_OFF +
- CONFIG_RW_STORAGE_OFF;
- uint32_t size = CONFIG_RW_SIZE;
- char *e;
-
- if (argc == 1) {
- ccprintf("Offset: 0x%08x\n", data_offset);
- ccprintf("Size: 0x%08x (%d)\n", data_size, data_size);
- ccprintf("Digest: ");
- if (want_abort)
- ccprintf("(aborting)\n");
- else if (in_progress)
- ccprintf("(in progress)\n");
- else if (hash)
- ccprintf("%ph\n", HEX_BUF(hash, SHA256_DIGEST_SIZE));
- else
- ccprintf("(invalid)\n");
-
- return EC_SUCCESS;
- }
-
- if (argc == 2) {
- if (!strcasecmp(argv[1], "abort")) {
- vboot_hash_abort();
- return EC_SUCCESS;
- } else if (!strcasecmp(argv[1], "rw")) {
- return vboot_hash_start(
- get_offset(EC_VBOOT_HASH_OFFSET_ACTIVE),
- get_rw_size(),
- NULL, 0, VBOOT_HASH_DEFERRED);
- } else if (!strcasecmp(argv[1], "ro")) {
- return vboot_hash_start(
- CONFIG_EC_PROTECTED_STORAGE_OFF +
- CONFIG_RO_STORAGE_OFF,
- system_get_image_used(EC_IMAGE_RO),
- NULL, 0, VBOOT_HASH_DEFERRED);
- }
- return EC_ERROR_PARAM2;
- }
-
- if (argc >= 3) {
- offset = strtoi(argv[1], &e, 0);
- if (*e)
- return EC_ERROR_PARAM1;
-
- size = strtoi(argv[2], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2;
- }
-
- if (argc == 4) {
- int nonce = strtoi(argv[3], &e, 0);
- if (*e)
- return EC_ERROR_PARAM3;
-
- return vboot_hash_start(offset, size,
- (const uint8_t *)&nonce,
- sizeof(nonce), VBOOT_HASH_DEFERRED);
- } else
- return vboot_hash_start(offset, size,
- NULL, 0, VBOOT_HASH_DEFERRED);
-}
-DECLARE_CONSOLE_COMMAND(hash, command_hash,
- "[abort | ro | rw] | [<offset> <size> [<nonce>]]",
- "Request hash recomputation");
-#endif /* CONFIG_CMD_HASH */
-/****************************************************************************/
-/* Host commands */
-
-/* Fill in the response with the current hash status */
-static void fill_response(struct ec_response_vboot_hash *r,
- int request_offset)
-{
- if (in_progress)
- r->status = EC_VBOOT_HASH_STATUS_BUSY;
- else if (get_offset(request_offset) == data_offset && hash &&
- !want_abort) {
- r->status = EC_VBOOT_HASH_STATUS_DONE;
- r->hash_type = EC_VBOOT_HASH_TYPE_SHA256;
- r->digest_size = SHA256_DIGEST_SIZE;
- r->reserved0 = 0;
- r->offset = data_offset;
- r->size = data_size;
- ASSERT(SHA256_DIGEST_SIZE < sizeof(r->hash_digest));
- memcpy(r->hash_digest, hash, SHA256_DIGEST_SIZE);
- } else
- r->status = EC_VBOOT_HASH_STATUS_NONE;
-}
-
-/**
- * Start computing a hash, with validity checking on params.
- *
- * @return EC_RES_SUCCESS if success, or other result code on error.
- */
-static int host_start_hash(const struct ec_params_vboot_hash *p)
-{
- int offset = p->offset;
- int size = p->size;
- int rv;
-
- /* Validity-check input params */
- if (p->hash_type != EC_VBOOT_HASH_TYPE_SHA256)
- return EC_RES_INVALID_PARAM;
- if (p->nonce_size > sizeof(p->nonce_data))
- return EC_RES_INVALID_PARAM;
-
- /* Handle special offset values */
- if (offset == EC_VBOOT_HASH_OFFSET_RO)
- size = system_get_image_used(EC_IMAGE_RO);
- else if ((offset == EC_VBOOT_HASH_OFFSET_ACTIVE) ||
- (offset == EC_VBOOT_HASH_OFFSET_UPDATE))
- size = get_rw_size();
- offset = get_offset(offset);
- rv = vboot_hash_start(offset, size, p->nonce_data, p->nonce_size,
- VBOOT_HASH_DEFERRED);
-
- if (rv == EC_SUCCESS)
- return EC_RES_SUCCESS;
- else if (rv == EC_ERROR_INVAL)
- return EC_RES_INVALID_PARAM;
- else
- return EC_RES_ERROR;
-}
-
-static enum ec_status
-host_command_vboot_hash(struct host_cmd_handler_args *args)
-{
- const struct ec_params_vboot_hash *p = args->params;
- struct ec_response_vboot_hash *r = args->response;
- int rv;
-
- switch (p->cmd) {
- case EC_VBOOT_HASH_GET:
- if (p->offset || p->size)
- fill_response(r, p->offset);
- else
- fill_response(r, data_offset);
-
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-
- case EC_VBOOT_HASH_ABORT:
- vboot_hash_abort();
- return EC_RES_SUCCESS;
-
- case EC_VBOOT_HASH_START:
- case EC_VBOOT_HASH_RECALC:
- rv = host_start_hash(p);
- if (rv != EC_RES_SUCCESS)
- return rv;
-
- /* Wait for hash to finish if command is RECALC */
- if (p->cmd == EC_VBOOT_HASH_RECALC)
- while (in_progress)
- usleep(1000);
-
- fill_response(r, p->offset);
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-
- default:
- return EC_RES_INVALID_PARAM;
- }
-}
-DECLARE_HOST_COMMAND(EC_CMD_VBOOT_HASH,
- host_command_vboot_hash,
- EC_VER_MASK(0));
diff --git a/common/virtual_battery.c b/common/virtual_battery.c
deleted file mode 100644
index 0f0167556c..0000000000
--- a/common/virtual_battery.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/* Copyright 2016 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.
- */
-
-/* Virtual battery cross-platform code for Chrome EC */
-
-#include "battery.h"
-#include "charge_state.h"
-#include "i2c.h"
-#include "system.h"
-#include "util.h"
-#include "virtual_battery.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_I2C, outstr)
-#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args)
-
-#define BATT_MODE_UNINITIALIZED -1
-
-/*
- * The state machine used to parse smart battery command
- * to support virtual battery.
- */
-enum batt_cmd_parse_state {
- IDLE = 0, /* initial state */
- START = 1, /* received the register address (command code) */
- WRITE_VB, /* writing data bytes to the peripheral */
- READ_VB, /* reading data bytes to the peripheral */
-};
-
-static enum batt_cmd_parse_state sb_cmd_state;
-static uint8_t cache_hit;
-static const uint8_t *batt_cmd_head;
-static int acc_write_len;
-
-int virtual_battery_handler(struct ec_response_i2c_passthru *resp,
- int in_len, int *err_code, int xferflags,
- int read_len, int write_len,
- const uint8_t *out)
-{
-
-#if defined(CONFIG_BATTERY_PRESENT_GPIO) || \
- defined(CONFIG_BATTERY_PRESENT_CUSTOM)
- /*
- * If the battery isn't present, return a NAK (which we
- * would have gotten anyways had we attempted to talk to
- * the battery.)
- */
- if (battery_is_present() != BP_YES) {
- resp->i2c_status = EC_I2C_STATUS_NAK;
- return EC_ERROR_INVAL;
- }
-#endif
- switch (sb_cmd_state) {
- case IDLE:
- /*
- * A legal battery command must start
- * with a i2c write for reg index.
- */
- if (write_len == 0) {
- resp->i2c_status = EC_I2C_STATUS_NAK;
- return EC_ERROR_INVAL;
- }
- /* Record the head of battery command. */
- batt_cmd_head = out;
- sb_cmd_state = START;
- *err_code = 0;
- break;
- case START:
- if (write_len > 0) {
- sb_cmd_state = WRITE_VB;
- *err_code = 0;
- } else {
- sb_cmd_state = READ_VB;
- *err_code = virtual_battery_operation(batt_cmd_head,
- NULL, 0, 0);
- /*
- * If the reg is not handled by virtual battery, we
- * do not support it.
- */
- if (*err_code)
- return EC_ERROR_INVAL;
- cache_hit = 1;
- }
- break;
- case WRITE_VB:
- if (write_len == 0) {
- resp->i2c_status = EC_I2C_STATUS_NAK;
- reset_parse_state();
- return EC_ERROR_INVAL;
- }
- *err_code = 0;
- break;
- case READ_VB:
- if (read_len == 0) {
- resp->i2c_status = EC_I2C_STATUS_NAK;
- reset_parse_state();
- return EC_ERROR_INVAL;
- }
- /*
- * Do not send the command to battery
- * if the reg is cached.
- */
- if (cache_hit)
- *err_code = 0;
- break;
- default:
- reset_parse_state();
- return EC_ERROR_INVAL;
- }
-
- acc_write_len += write_len;
-
- /* the last message */
- if (xferflags & I2C_XFER_STOP) {
- switch (sb_cmd_state) {
- /* write to virtual battery */
- case START:
- case WRITE_VB:
- virtual_battery_operation(batt_cmd_head,
- NULL,
- 0,
- acc_write_len);
- break;
- /* read from virtual battery */
- case READ_VB:
- if (cache_hit) {
- read_len += in_len;
- memset(&resp->data[0], 0, read_len);
- virtual_battery_operation(batt_cmd_head,
- &resp->data[0],
- read_len,
- 0);
- }
- break;
- default:
- reset_parse_state();
- return EC_ERROR_INVAL;
-
- }
- /* Reset the state in the end of messages */
- reset_parse_state();
- }
- return EC_RES_SUCCESS;
-}
-
-void reset_parse_state(void)
-{
- sb_cmd_state = IDLE;
- cache_hit = 0;
- acc_write_len = 0;
-}
-
-/*
- * Copy memmap string data from offset to dest, up to size len, in the format
- * expected by SBS (first byte of dest contains strlen).
- */
-void copy_memmap_string(uint8_t *dest, int offset, int len)
-{
- uint8_t *memmap_str;
- uint8_t memmap_strlen;
-
- if (len == 0)
- return;
- memmap_str = host_get_memmap(offset);
- /* memmap_str might not be NULL terminated */
- memmap_strlen = *(memmap_str + EC_MEMMAP_TEXT_MAX - 1) == '\0' ?
- strlen(memmap_str) : EC_MEMMAP_TEXT_MAX;
- dest[0] = memmap_strlen;
- memcpy(dest + 1, memmap_str, MIN(memmap_strlen, len - 1));
-}
-
-int virtual_battery_operation(const uint8_t *batt_cmd_head,
- uint8_t *dest,
- int read_len,
- int write_len)
-{
- int val;
- int year, month, day;
- /*
- * We cache battery operational mode locally for both read and write
- * commands. If MODE_CAPACITY bit is set, battery capacity will be
- * reported in 10mW/10mWh, instead of the default unit, mA/mAh.
- * Note that we don't update the cached capacity: We do a real-time
- * conversion and return the converted values.
- */
- static int batt_mode_cache = BATT_MODE_UNINITIALIZED;
- const struct batt_params *curr_batt;
- /*
- * Don't allow host reads into arbitrary memory space, most params
- * are two bytes.
- */
- int bounded_read_len = MIN(read_len, 2);
-
- curr_batt = charger_current_battery_params();
- switch (*batt_cmd_head) {
- case SB_BATTERY_MODE:
- if (write_len == 3) {
- batt_mode_cache = batt_cmd_head[1] |
- (batt_cmd_head[2] << 8);
- } else if (read_len > 0) {
- if (batt_mode_cache == BATT_MODE_UNINITIALIZED)
- /*
- * Read the battery operational mode from
- * the battery to initialize batt_mode_cache.
- * This may cause an i2c transaction.
- */
- if (battery_get_mode(&batt_mode_cache) ==
- EC_ERROR_UNIMPLEMENTED)
- /*
- * Register not supported, choose
- * typical SB defaults.
- */
- batt_mode_cache =
- MODE_INTERNAL_CHARGE_CONTROLLER |
- MODE_ALARM |
- MODE_CHARGER;
-
- memcpy(dest, &batt_mode_cache, bounded_read_len);
- }
- break;
- case SB_SERIAL_NUMBER:
- val = strtoi(host_get_memmap(EC_MEMMAP_BATT_SERIAL), NULL, 16);
- memcpy(dest, &val, bounded_read_len);
- break;
- case SB_VOLTAGE:
- if (curr_batt->flags & BATT_FLAG_BAD_VOLTAGE)
- return EC_ERROR_BUSY;
- memcpy(dest, &(curr_batt->voltage), bounded_read_len);
- break;
- case SB_RELATIVE_STATE_OF_CHARGE:
- if (curr_batt->flags & BATT_FLAG_BAD_STATE_OF_CHARGE)
- return EC_ERROR_BUSY;
- memcpy(dest, &(curr_batt->state_of_charge), bounded_read_len);
- break;
- case SB_TEMPERATURE:
- if (curr_batt->flags & BATT_FLAG_BAD_TEMPERATURE)
- return EC_ERROR_BUSY;
- memcpy(dest, &(curr_batt->temperature), bounded_read_len);
- break;
- case SB_CURRENT:
- if (curr_batt->flags & BATT_FLAG_BAD_CURRENT)
- return EC_ERROR_BUSY;
- memcpy(dest, &(curr_batt->current), bounded_read_len);
- break;
- case SB_AVERAGE_CURRENT:
- /* This may cause an i2c transaction */
- if (curr_batt->flags & BATT_FLAG_BAD_AVERAGE_CURRENT)
- return EC_ERROR_BUSY;
- val = battery_get_avg_current();
- memcpy(dest, &val, bounded_read_len);
- break;
- case SB_MAX_ERROR:
- /* report as 3% to make kernel happy */
- val = BATTERY_LEVEL_SHUTDOWN;
- memcpy(dest, &val, bounded_read_len);
- break;
- case SB_FULL_CHARGE_CAPACITY:
- if (curr_batt->flags & BATT_FLAG_BAD_FULL_CAPACITY ||
- curr_batt->flags & BATT_FLAG_BAD_VOLTAGE)
- return EC_ERROR_BUSY;
- val = curr_batt->full_capacity;
- if (batt_mode_cache & MODE_CAPACITY)
- val = val * curr_batt->voltage / 10000;
- memcpy(dest, &val, bounded_read_len);
- break;
- case SB_BATTERY_STATUS:
- if (curr_batt->flags & BATT_FLAG_BAD_STATUS)
- return EC_ERROR_BUSY;
- memcpy(dest, &(curr_batt->status), bounded_read_len);
- break;
- case SB_CYCLE_COUNT:
- memcpy(dest, (int *)host_get_memmap(EC_MEMMAP_BATT_CCNT),
- bounded_read_len);
- break;
- case SB_DESIGN_CAPACITY:
- if (curr_batt->flags & BATT_FLAG_BAD_VOLTAGE)
- return EC_ERROR_BUSY;
- val = *(int *)host_get_memmap(EC_MEMMAP_BATT_DCAP);
- if (batt_mode_cache & MODE_CAPACITY)
- val = val * curr_batt->voltage / 10000;
- memcpy(dest, &val, bounded_read_len);
- break;
- case SB_DESIGN_VOLTAGE:
- memcpy(dest, (int *)host_get_memmap(EC_MEMMAP_BATT_DVLT),
- bounded_read_len);
- break;
- case SB_REMAINING_CAPACITY:
- if (curr_batt->flags & BATT_FLAG_BAD_REMAINING_CAPACITY ||
- curr_batt->flags & BATT_FLAG_BAD_VOLTAGE)
- return EC_ERROR_BUSY;
- val = curr_batt->remaining_capacity;
- if (batt_mode_cache & MODE_CAPACITY)
- val = val * curr_batt->voltage / 10000;
- memcpy(dest, &val, bounded_read_len);
- break;
- case SB_MANUFACTURER_NAME:
- copy_memmap_string(dest, EC_MEMMAP_BATT_MFGR, read_len);
- break;
- case SB_DEVICE_NAME:
- copy_memmap_string(dest, EC_MEMMAP_BATT_MODEL, read_len);
- break;
- case SB_DEVICE_CHEMISTRY:
- copy_memmap_string(dest, EC_MEMMAP_BATT_TYPE, read_len);
- break;
- case SB_AVERAGE_TIME_TO_FULL:
- /* This may cause an i2c transaction */
- if (battery_time_to_full(&val))
- return EC_ERROR_INVAL;
- memcpy(dest, &val, bounded_read_len);
- break;
- case SB_AVERAGE_TIME_TO_EMPTY:
- /* This may cause an i2c transaction */
- if (battery_time_to_empty(&val))
- return EC_ERROR_INVAL;
- memcpy(dest, &val, bounded_read_len);
- break;
- case SB_CHARGING_CURRENT:
- if (curr_batt->flags & BATT_FLAG_BAD_DESIRED_CURRENT)
- return EC_ERROR_BUSY;
- val = curr_batt->desired_current;
- memcpy(dest, &val, bounded_read_len);
- break;
- case SB_CHARGING_VOLTAGE:
- if (curr_batt->flags & BATT_FLAG_BAD_DESIRED_VOLTAGE)
- return EC_ERROR_BUSY;
- val = curr_batt->desired_voltage;
- memcpy(dest, &val, bounded_read_len);
- break;
- case SB_MANUFACTURE_DATE:
- /* This may cause an i2c transaction */
- if (!battery_manufacture_date(&year, &month, &day)) {
- /* Encode in Smart Battery Spec format */
- val = ((year - 1980) << 9) + (month << 5) + day;
- } else {
- /*
- * Return 0 on error. The kernel is unhappy with
- * returning an error code.
- */
- val = 0;
- }
- memcpy(dest, &val, bounded_read_len);
- break;
- case SB_MANUFACTURER_ACCESS:
- /* No manuf. access reg access allowed over VB interface */
- return EC_ERROR_INVAL;
- case SB_SPECIFICATION_INFO:
- /* v1.1 without PEC, no scale factor to voltage and current */
- val = 0x0011;
- memcpy(dest, &val, bounded_read_len);
- break;
- default:
- CPRINTS("Unhandled VB reg %x", *batt_cmd_head);
- return EC_ERROR_INVAL;
- }
- return EC_SUCCESS;
-}
-
diff --git a/common/vstore.c b/common/vstore.c
deleted file mode 100644
index 9b4636397c..0000000000
--- a/common/vstore.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/* Copyright 2015 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.
- */
-
-/*
- * Temporary secure storage commands for use by the host for verified boot
- * related activities such as storing the hash of verified firmware for use
- * in suspend/resume.
- *
- * There are a configurable number of vstore slots, with all slots having
- * the same size of EC_VSTORE_SLOT_SIZE (64 bytes).
- *
- * Slots can be written once per AP power-on and will then be locked and
- * cannot be written again until it is cleared in the CHIPSET_SHUTDOWN
- * or CHIPSET_RESET hooks.
- */
-
-#include "common.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "system.h"
-#include "util.h"
-
-#define VSTORE_SYSJUMP_TAG 0x5653 /* "VS" */
-#define VSTORE_HOOK_VERSION 1
-
-struct vstore_slot {
- uint8_t locked;
- uint8_t data[EC_VSTORE_SLOT_SIZE];
-};
-
-static struct vstore_slot vstore_slots[CONFIG_VSTORE_SLOT_COUNT];
-static const int vstore_size =
- sizeof(struct vstore_slot) * CONFIG_VSTORE_SLOT_COUNT;
-BUILD_ASSERT(ARRAY_SIZE(vstore_slots) <= EC_VSTORE_SLOT_MAX);
-
-/*
- * vstore_info - Get slot count and mask of locked slots.
- */
-static enum ec_status vstore_info(struct host_cmd_handler_args *args)
-{
- struct ec_response_vstore_info *r = args->response;
- int i;
-
- r->slot_count = CONFIG_VSTORE_SLOT_COUNT;
- r->slot_locked = 0;
- for (i = 0; i < CONFIG_VSTORE_SLOT_COUNT; i++)
- if (vstore_slots[i].locked)
- r->slot_locked |= 1 << i;
-
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_VSTORE_INFO, vstore_info, EC_VER_MASK(0));
-
-/*
- * vstore_read - Read slot from temporary secure storage.
- *
- * Response is EC_VSTORE_SLOT_SIZE bytes of data.
- */
-static enum ec_status vstore_read(struct host_cmd_handler_args *args)
-{
- const struct ec_params_vstore_read *p = args->params;
- struct ec_response_vstore_read *r = args->response;
-
- if (p->slot >= CONFIG_VSTORE_SLOT_COUNT)
- return EC_RES_INVALID_PARAM;
-
- memcpy(r->data, vstore_slots[p->slot].data, EC_VSTORE_SLOT_SIZE);
-
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_VSTORE_READ, vstore_read, EC_VER_MASK(0));
-
-/*
- * vstore_write - Write temporary secure storage slot and lock it.
- */
-static enum ec_status vstore_write(struct host_cmd_handler_args *args)
-{
- const struct ec_params_vstore_write *p = args->params;
- struct vstore_slot *slot;
-
- if (p->slot >= CONFIG_VSTORE_SLOT_COUNT)
- return EC_RES_INVALID_PARAM;
- slot = &vstore_slots[p->slot];
-
- if (slot->locked)
- return EC_RES_ACCESS_DENIED;
- slot->locked = 1;
- memcpy(slot->data, p->data, EC_VSTORE_SLOT_SIZE);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_VSTORE_WRITE, vstore_write, EC_VER_MASK(0));
-
-static void vstore_clear_lock(void)
-{
- int i;
-
- for (i = 0; i < CONFIG_VSTORE_SLOT_COUNT; i++)
- vstore_slots[i].locked = 0;
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESET, vstore_clear_lock, HOOK_PRIO_DEFAULT);
-
-static void vstore_preserve_state(void)
-{
- system_add_jump_tag(VSTORE_SYSJUMP_TAG, VSTORE_HOOK_VERSION,
- vstore_size, vstore_slots);
-}
-DECLARE_HOOK(HOOK_SYSJUMP, vstore_preserve_state, HOOK_PRIO_DEFAULT);
-
-static void vstore_init(void)
-{
- const struct vstore_slot *prev;
- int version, size;
-
- prev = (const struct vstore_slot *)system_get_jump_tag(
- VSTORE_SYSJUMP_TAG, &version, &size);
-
- if (prev && version == VSTORE_HOOK_VERSION && size == vstore_size)
- memcpy(vstore_slots, prev, vstore_size);
-}
-DECLARE_HOOK(HOOK_INIT, vstore_init, HOOK_PRIO_DEFAULT);
diff --git a/common/webusb_desc.c b/common/webusb_desc.c
deleted file mode 100644
index 41d39006e0..0000000000
--- a/common/webusb_desc.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Copyright 2017 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.
- */
-/* WebUSB platform descriptor */
-
-#include "common.h"
-#include "usb_descriptor.h"
-#include "util.h"
-
-#ifndef CONFIG_USB_BOS
-#error "CONFIG_USB_BOS must be defined to use WebUSB descriptor"
-#endif
-
-const void *webusb_url = USB_URL_DESC(HTTPS, CONFIG_WEBUSB_URL);
-
-/*
- * Platform Descriptor in the device Binary Object Store
- * as defined by USB 3.1 spec chapter 9.6.2.
- */
-static struct {
- struct usb_bos_hdr_descriptor bos;
- struct usb_platform_descriptor platform;
-} bos_desc = {
- .bos = {
- .bLength = USB_DT_BOS_SIZE,
- .bDescriptorType = USB_DT_BOS,
- .wTotalLength = (USB_DT_BOS_SIZE + USB_DT_PLATFORM_SIZE),
- .bNumDeviceCaps = 1, /* platform caps */
- },
- .platform = {
- .bLength = USB_DT_PLATFORM_SIZE,
- .bDescriptorType = USB_DT_DEVICE_CAPABILITY,
- .bDevCapabilityType = USB_DC_DTYPE_PLATFORM,
- .bReserved = 0,
- .PlatformCapUUID = USB_PLAT_CAP_WEBUSB,
- .bcdVersion = 0x0100,
- .bVendorCode = 0x01,
- .iLandingPage = 1,
- },
-};
-
-const struct bos_context bos_ctx = {
- .descp = (void *)&bos_desc,
- .size = sizeof(bos_desc),
-};
diff --git a/common/wireless.c b/common/wireless.c
deleted file mode 100644
index d1f5cad645..0000000000
--- a/common/wireless.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/* Copyright 2013 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.
- */
-
-/* Wireless power management */
-
-#include "common.h"
-#include "console.h"
-#include "gpio.h"
-#include "host_command.h"
-#include "util.h"
-#include "wireless.h"
-
-/* Unless told otherwise, disable wireless in suspend */
-#ifndef CONFIG_WIRELESS_SUSPEND
-#define CONFIG_WIRELESS_SUSPEND 0
-#endif
-
-/*
- * Flags which will be left on when suspending. Other flags will be disabled
- * when suspending.
- */
-static int suspend_flags = CONFIG_WIRELESS_SUSPEND;
-
-/**
- * Set wireless switch state.
- *
- * @param flags Enable flags from ec_commands.h (EC_WIRELESS_SWITCH_*),
- * 0 to turn all wireless off, or -1 to turn all wireless
- * on.
- * @param mask Which of those flags to set
- */
-static void wireless_enable(int flags)
-{
-#ifdef WIRELESS_GPIO_WLAN
- gpio_set_level(WIRELESS_GPIO_WLAN,
- flags & EC_WIRELESS_SWITCH_WLAN);
-#endif
-
-#ifdef WIRELESS_GPIO_WWAN
- gpio_set_level(WIRELESS_GPIO_WWAN,
- flags & EC_WIRELESS_SWITCH_WWAN);
-#endif
-
-#ifdef WIRELESS_GPIO_BLUETOOTH
- gpio_set_level(WIRELESS_GPIO_BLUETOOTH,
- flags & EC_WIRELESS_SWITCH_BLUETOOTH);
-#endif
-
-#ifdef WIRELESS_GPIO_WLAN_POWER
-#ifndef CONFIG_WLAN_POWER_ACTIVE_LOW
- gpio_set_level(WIRELESS_GPIO_WLAN_POWER,
- flags & EC_WIRELESS_SWITCH_WLAN_POWER);
-#else
- gpio_set_level(WIRELESS_GPIO_WLAN_POWER,
- !(flags & EC_WIRELESS_SWITCH_WLAN_POWER));
-#endif /* CONFIG_WLAN_POWER_ACTIVE_LOW */
-#endif
-
-}
-
-static int wireless_get(void)
-{
- int flags = 0;
-
-#ifdef WIRELESS_GPIO_WLAN
- if (gpio_get_level(WIRELESS_GPIO_WLAN))
- flags |= EC_WIRELESS_SWITCH_WLAN;
-#endif
-
-#ifdef WIRELESS_GPIO_WWAN
- if (gpio_get_level(WIRELESS_GPIO_WWAN))
- flags |= EC_WIRELESS_SWITCH_WWAN;
-#endif
-
-#ifdef WIRELESS_GPIO_BLUETOOTH
- if (gpio_get_level(WIRELESS_GPIO_BLUETOOTH))
- flags |= EC_WIRELESS_SWITCH_BLUETOOTH;
-#endif
-
-#ifdef WIRELESS_GPIO_WLAN_POWER
-#ifndef CONFIG_WLAN_POWER_ACTIVE_LOW
- if (gpio_get_level(WIRELESS_GPIO_WLAN_POWER))
-#else
- if (!gpio_get_level(WIRELESS_GPIO_WLAN_POWER))
-#endif /* CONFIG_WLAN_POWER_ACTIVE_LOW */
- flags |= EC_WIRELESS_SWITCH_WLAN_POWER;
-#endif
-
- return flags;
-}
-
-void wireless_set_state(enum wireless_power_state state)
-{
- switch (state) {
- case WIRELESS_OFF:
- wireless_enable(0);
- break;
- case WIRELESS_SUSPEND:
- /*
- * When suspending, only turn things off. If the AP has
- * disabled WiFi power, going into S3 should not re-enable it.
- */
- wireless_enable(wireless_get() & suspend_flags);
- break;
- case WIRELESS_ON:
- wireless_enable(EC_WIRELESS_SWITCH_ALL);
- break;
- }
-}
-
-static enum ec_status wireless_enable_cmd(struct host_cmd_handler_args *args)
-{
- const struct ec_params_switch_enable_wireless_v1 *p = args->params;
- struct ec_response_switch_enable_wireless_v1 *r = args->response;
-
- if (args->version == 0) {
- /* Ver.0 command just set all current flags */
- wireless_enable(p->now_flags);
- return EC_RES_SUCCESS;
- }
-
- /* Ver.1 can set flags based on mask */
- wireless_enable((wireless_get() & ~p->now_mask) |
- (p->now_flags & p->now_mask));
-
- suspend_flags = (suspend_flags & ~p->suspend_mask) |
- (p->suspend_flags & p->suspend_mask);
-
- /* And return the current flags */
- r->now_flags = wireless_get();
- r->suspend_flags = suspend_flags;
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_SWITCH_ENABLE_WIRELESS,
- wireless_enable_cmd,
- EC_VER_MASK(0) | EC_VER_MASK(1));
-
-static int command_wireless(int argc, char **argv)
-{
- char *e;
- int i;
-
- if (argc >= 2) {
- i = strtoi(argv[1], &e, 0);
- if (*e)
- return EC_ERROR_PARAM1;
-
- wireless_enable(i);
- }
-
- if (argc >= 3) {
- i = strtoi(argv[2], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2;
-
- suspend_flags = i;
- }
-
- ccprintf("Wireless flags: now=0x%x, suspend=0x%x\n", wireless_get(),
- suspend_flags);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(wireless, command_wireless,
- "[now [suspend]]",
- "Get/set wireless flags");