summaryrefslogtreecommitdiff
path: root/zephyr/test/drivers
diff options
context:
space:
mode:
authorAseda Aboagye <aaboagye@google.com>2022-01-10 17:26:56 -0600
committerAseda Aboagye <aaboagye@google.com>2022-01-10 17:26:56 -0600
commitdc11829e169a9c425860ec5cca949ef80df9e0b7 (patch)
tree0517b0831c6e52b347926a1b727741df380e908c /zephyr/test/drivers
parentc5bd23a4b204565dab616f7fa4ee8a0b7b433d4c (diff)
parentb44d10f8f79cadb259cc7ab79714a0919fc0c4c8 (diff)
downloadchrome-ec-dc11829e169a9c425860ec5cca949ef80df9e0b7.tar.gz
Merge remote-tracking branch cros/main into firmware-keeby-14119.B-mainfirmware-keeby-14119.B-main
Relevant changes: git log --oneline c5bd23a4b..b44d10f8f -- baseboard/dedede board/cappy2 board/corori board/driblee board/gooey board/haboki board/lalala board/waddledoo2 common/charge_state_v2.c common/mkbp_* common/ocpc.c common/usbc/usb_tc_drp_acc_trysrc_sm.c common/usbc/usb_sm.c common/usbc/*_pd_* common/usbc/dp_alt_mode.c common/usbc/usb_prl_sm.c common/usbc/usb_pe_drp_sm.c common/usb_charger.c common/usb_common.c common/usbc_ocp.c driver/charger/sm5803.* driver/charger/isl923x.* driver/tcpm/raa489000.* driver/tcpm/it83* include/power/icelake.h include/intel_x86.h power/icelake.c power/intel_x86.c util/getversion.sh 42d03a001 config: change temp_sensor_power from config to gpio e296efb28 usb_common: Fix CONFIG_USB_PD_DISCHARGE_TCPC typo c346481f4 atomic: cast to unsigned when shifting 9b972a0f2 driver/tcpm/it83xx, it8xxx2: ITE inactive port return from HOOK a499d8fd4 driver/tcpm/it83xx, it8xxx2: set sleep mask for mixed TCPC case ed62e2583 TCPMv2: don't set the sleep mask for TCPC embedded in EC c962696e8 motion_sensor: Remove |int_signal| field 86b216794 ocpc: modify pre-charge target condition 6f8336eb4 dedede: Set MKBP event wake mask to 0 02d034df0 dedede: add stylus fw_config 4f7cd7509 atomic: use atomic_t where it is possible e3ffa0519 mkbp: change the type fifo_entries to atomic_t bb4c47af0 usb: use atomic_t where possible c6e513ee2 power/icelake: Add SLP_S5 as a watched power signal d89e49b20 power: Introduce S4 as a real power state ba8a3c9c0 chgstv2: Use chipset_in_state instead of naming states 23a975d12 i2c: Use declared initializers for i2c_ports: boards a-l 35865dbec TCPMv2: Guard DATA_RESET using CONFIG_USB_PD_DATA_RESET_MSG d4d8243ed i2c: Use declared initializers for i2c_ports: baseboards eba8d0305 RAA489000: Fixed RAA489000 max charging current e78b83e0f TCPMv2: Delay Data Reset until mode entry request 6230e60fc TCPMv2: Support Data Reset as DFP, initiator 412246836 intel_x86: Apply chipset resume init and suspend complete hooks f2809b72c config: rename CONFIG_HOSTCMD_ESPI to CONFIG_HOST_INTERFACE_ESPI BRANCH=None BUG=b:202796060 b:207805856 b:167983049 b:208318528 b:181983966 BUG=b:207328258 b:195416058 b:205285137 b:199919093 b:207055975 BUG=b:129159505 b:204947672 b:141363146 b:207082842 b:205675485 TEST=`make -j buildall` Signed-off-by: Aseda Aboagye <aaboagye@google.com> Change-Id: I980351977e11088a130e478df0701be4715f049b
Diffstat (limited to 'zephyr/test/drivers')
-rw-r--r--zephyr/test/drivers/include/gpio_map.h18
-rw-r--r--zephyr/test/drivers/include/stubs.h15
-rw-r--r--zephyr/test/drivers/include/test_mocks.h26
-rw-r--r--zephyr/test/drivers/overlay.dts82
-rw-r--r--zephyr/test/drivers/prj.conf7
-rw-r--r--zephyr/test/drivers/src/bb_retimer.c16
-rw-r--r--zephyr/test/drivers/src/bmi160.c2
-rw-r--r--zephyr/test/drivers/src/bmi260.c2
-rw-r--r--zephyr/test/drivers/src/cros_cbi.c24
-rw-r--r--zephyr/test/drivers/src/espi.c3
-rw-r--r--zephyr/test/drivers/src/integration_usb.c187
-rw-r--r--zephyr/test/drivers/src/isl923x.c463
-rw-r--r--zephyr/test/drivers/src/lis2dw12.c363
-rw-r--r--zephyr/test/drivers/src/main.c4
-rw-r--r--zephyr/test/drivers/src/power_common.c677
-rw-r--r--zephyr/test/drivers/src/ppc.c328
-rw-r--r--zephyr/test/drivers/src/ppc_sn5s330.c326
-rw-r--r--zephyr/test/drivers/src/ps8xxx.c13
-rw-r--r--zephyr/test/drivers/src/stubs.c144
-rw-r--r--zephyr/test/drivers/src/tcpci.c7
-rw-r--r--zephyr/test/drivers/src/tcpci_test_common.c11
-rw-r--r--zephyr/test/drivers/src/usb_mux.c623
22 files changed, 2944 insertions, 397 deletions
diff --git a/zephyr/test/drivers/include/gpio_map.h b/zephyr/test/drivers/include/gpio_map.h
index 5253b0155a..1255348a61 100644
--- a/zephyr/test/drivers/include/gpio_map.h
+++ b/zephyr/test/drivers/include/gpio_map.h
@@ -17,13 +17,17 @@
* Note we only need to create aliases for GPIOs that are referenced in common
* platform/ec code.
*/
-#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_PG_EC_DSW_PWROK
+#define GPIO_TEMP_SENSOR_POWER GPIO_PG_EC_DSW_PWROK
-#define EC_CROS_GPIO_INTERRUPTS \
- GPIO_INT(GPIO_AC_PRESENT, GPIO_INT_EDGE_BOTH, extpower_interrupt) \
- GPIO_INT(GPIO_USB_C0_TCPC_INT_ODL, GPIO_INT_EDGE_FALLING, \
- tcpc_alert_event) \
- GPIO_INT(GPIO_USB_C1_TCPC_INT_ODL, GPIO_INT_EDGE_FALLING, \
- tcpc_alert_event)
+#define EC_CROS_GPIO_INTERRUPTS \
+ GPIO_INT(GPIO_AC_PRESENT, GPIO_INT_EDGE_BOTH, extpower_interrupt) \
+ GPIO_INT(GPIO_USB_C0_TCPC_INT_ODL, GPIO_INT_EDGE_FALLING, \
+ tcpc_alert_event) \
+ GPIO_INT(GPIO_USB_C1_TCPC_INT_ODL, GPIO_INT_EDGE_FALLING, \
+ tcpc_alert_event) \
+ GPIO_INT(GPIO_USB_C0_PPC_INT_ODL, GPIO_INT_EDGE_FALLING, ppc_alert) \
+ GPIO_INT(GPIO_USB_C1_PPC_INT_ODL, GPIO_INT_EDGE_FALLING, ppc_alert) \
+ GPIO_INT(GPIO_SWITCHCAP_PG_INT_L, GPIO_INT_EDGE_FALLING, \
+ ln9310_interrupt) \
#endif /* __ZEPHYR_GPIO_MAP_H */
diff --git a/zephyr/test/drivers/include/stubs.h b/zephyr/test/drivers/include/stubs.h
index 448d6c883b..af32a988c6 100644
--- a/zephyr/test/drivers/include/stubs.h
+++ b/zephyr/test/drivers/include/stubs.h
@@ -6,6 +6,7 @@
#ifndef __TEST_DRIVERS_STUBS_H
#define __TEST_DRIVERS_STUBS_H
+#include "fff.h"
#include "power.h"
enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT };
@@ -13,7 +14,16 @@ enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT };
/* Structure used by usb_mux test. It is part of usb_muxes chain. */
extern struct usb_mux usbc1_virtual_usb_mux;
-void set_mock_power_state(enum power_state state);
+/**
+ * @brief Set state which should be returned by power_handle_state() and wake
+ * chipset task to immediately change state
+ *
+ * @param force If true @p state will be used as return for power_handle_state()
+ * and will wake up chipset task. If false argument of
+ * power_handle_state() will be used as return value
+ * @param state Power state to use when @p force is true
+ */
+void force_power_state(bool force, enum power_state state);
/**
* @brief Set product ID that should be returned by board_get_ps8xxx_product_id
@@ -22,4 +32,7 @@ void set_mock_power_state(enum power_state state);
*/
void board_set_ps8xxx_product_id(uint16_t product_id);
+/* Declare fake function to allow tests to examine calls to this function */
+DECLARE_FAKE_VOID_FUNC(system_hibernate, uint32_t, uint32_t);
+
#endif /* __TEST_DRIVERS_STUBS_H */
diff --git a/zephyr/test/drivers/include/test_mocks.h b/zephyr/test/drivers/include/test_mocks.h
index fe63eea0d3..3630df083f 100644
--- a/zephyr/test/drivers/include/test_mocks.h
+++ b/zephyr/test/drivers/include/test_mocks.h
@@ -53,7 +53,7 @@
#EXPECTED_REG ") but wrote to reg 0x%02x", \
(CALL_NUM), (EXPECTED_REG), \
FAKE##_fake.arg1_history[(CALL_NUM)]); \
- if (EXPECTED_VAL != MOCK_IGNORE_VALUE) { \
+ if ((EXPECTED_VAL) != MOCK_IGNORE_VALUE) { \
zassert_equal( \
FAKE##_fake.arg2_history[(CALL_NUM)], \
(EXPECTED_VAL), \
@@ -70,6 +70,30 @@
*/
#define MOCK_IGNORE_VALUE (-1)
+/**
+ * @brief Helper macro for asserting that a certain register read occurred.
+ * Used when wrapping an I2C emulator mock read function in FFF. Prints
+ * useful error messages when the assertion fails.
+ * @param FAKE - name of the fake whose arg history to insepct. Do not include
+ * '_fake' at the end.
+ * @param CALL_NUM - Index in to the call history that this write should have
+ * occurred at. Zero based.
+ * @param EXPECTED_REG - The register address that was supposed to be read
+ * from.
+ */
+#define MOCK_ASSERT_I2C_READ(FAKE, CALL_NUM, EXPECTED_REG) \
+ do { \
+ zassert_true((CALL_NUM) < FAKE##_fake.call_count, \
+ "Call #%d did not occur (%d I2C reads total)", \
+ (CALL_NUM), FAKE##_fake.call_count); \
+ zassert_equal( \
+ FAKE##_fake.arg1_history[(CALL_NUM)], (EXPECTED_REG), \
+ "Expected I2C read #%d from register 0x%02x (" \
+ #EXPECTED_REG ") but read from reg 0x%02x", \
+ (CALL_NUM), (EXPECTED_REG), \
+ FAKE##_fake.arg1_history[(CALL_NUM)]); \
+ } while (0)
+
/*
* Mock declarations
*/
diff --git a/zephyr/test/drivers/overlay.dts b/zephyr/test/drivers/overlay.dts
index fc0ddc0a6e..f45210d621 100644
--- a/zephyr/test/drivers/overlay.dts
+++ b/zephyr/test/drivers/overlay.dts
@@ -8,6 +8,11 @@
#include <freq.h>
/ {
+ chosen {
+ cros-ec,adc = &adc0;
+ cros-ec,espi = &espi0;
+ };
+
aliases {
bmi260-int = &ms_bmi260_accel;
bmi160-int = &ms_bmi160_accel;
@@ -20,12 +25,10 @@
ec_batt_pres_odl {
gpios = <&gpio0 1 GPIO_INPUT>;
enum-name = "GPIO_BATT_PRES_ODL";
- label = "EC_BATT_PRES_ODL";
};
acok_od {
gpios = <&gpio0 2 GPIO_INPUT>;
enum-name = "GPIO_AC_PRESENT";
- label = "ACOK_OD";
};
/* In test WP is output because CBI use it, but it is also
* input, because test_all_tags set it to enable write
@@ -35,54 +38,56 @@
#gpio-cells = <0>;
gpios = <&gpio0 3 (GPIO_INPUT | GPIO_OUTPUT)>;
enum-name = "GPIO_WP_L";
- label = "WP_L";
};
pg_ec_dsw_pwrok {
gpios = <&gpio0 4 GPIO_INPUT>;
enum-name = "GPIO_PG_EC_DSW_PWROK";
- label = "PG_EC_DSW_PWROK";
};
ec_pch_wake_odl {
gpios = <&gpio0 5 GPIO_OUT_HIGH>;
enum-name = "GPIO_EC_PCH_WAKE_ODL";
- label = "EC_PCH_WAKE_ODL";
};
/* Setup USB C1 pin as output to check their state in test */
usb_c1_ls_en {
- gpios = <&gpio0 6 (GPIO_INPUT | GPIO_PULL_UP |
+ gpios = <&gpio0 6 (GPIO_INPUT_PULL_UP |
GPIO_OUTPUT)>;
enum-name = "GPIO_USB_C1_LS_EN";
- label = "USB_C1_LS_EN";
};
usb_c1_rt_rst_odl {
gpios = <&gpio0 7 (GPIO_OUTPUT | GPIO_INPUT)>;
enum-name = "GPIO_USB_C1_RT_RST_ODL";
- label = "USB_C1_RT_RST_ODL";
};
gpio_usb_c1_frs_en: usb_c1_frs_en {
gpios = <&gpio0 8 (GPIO_OUT_LOW)>;
enum-name = "GPIO_USB_C1_FRS_EN";
- label = "USB_C1_FRS_EN";
};
usb_c0_tcpc_int_odl: usb_c0_tcpc_int_odl {
gpios = <&gpio0 9 GPIO_INPUT>;
enum-name = "GPIO_USB_C0_TCPC_INT_ODL";
- label = "USB_C0_TCPC_INT_ODL";
};
usb_c1_tcpc_int_odl: usb_c1_tcpc_int_odl {
gpios = <&gpio0 10 GPIO_INPUT>;
enum-name = "GPIO_USB_C1_TCPC_INT_ODL";
- label = "USB_C1_TCPC_INT_ODL";
};
usb_c0_tcpc_rst_l {
gpios = <&gpio0 11 (GPIO_OUT_HIGH | GPIO_INPUT)>;
enum-name = "GPIO_USB_C0_TCPC_RST_L";
- label = "USB_C0_TCPC_RST_L";
};
usb_c1_tcpc_rst_l {
gpios = <&gpio0 12 (GPIO_OUT_HIGH | GPIO_INPUT)>;
enum-name = "GPIO_USB_C1_TCPC_RST_L";
- label = "USB_C1_TCPC_RST_L";
+ };
+ gpio_usb_c1_ppc_int: usb_c1_ppc_int {
+ gpios = <&gpio0 13 GPIO_INPUT>;
+ enum-name = "GPIO_USB_C1_PPC_INT_ODL";
+ };
+ gpio_usb_c0_ppc_int: usb_c0_ppc_int {
+ gpios = <&gpio0 14 GPIO_INPUT>;
+ enum-name = "GPIO_USB_C0_PPC_INT_ODL";
+ };
+ gpio_switchcap_pg_int_l: switchcap_pg_int_l {
+ gpios = <&gpio0 15 GPIO_INPUT>;
+ enum-name = "GPIO_SWITCHCAP_PG_INT_L";
};
};
named-i2c-ports {
@@ -91,42 +96,34 @@
usb-c0 {
i2c-port = <&i2c0>;
enum-name = "I2C_PORT_USB_C0";
- label = "USB_C0";
};
usb-c1 {
i2c-port = <&i2c1>;
enum-name = "I2C_PORT_USB_C1";
- label = "USB_C1";
};
battery {
i2c-port = <&i2c0>;
enum-name = "I2C_PORT_BATTERY";
- label = "BATTERY";
};
power {
i2c-port = <&i2c0>;
enum-name = "I2C_PORT_POWER";
- label = "POWER";
};
charger {
i2c-port = <&i2c0>;
enum-name = "I2C_PORT_CHARGER";
- label = "CHARGER";
};
eeprom {
i2c-port = <&i2c0>;
enum-name = "I2C_PORT_EEPROM";
- label = "EEPROM";
};
i2c_accel: accel {
i2c-port = <&i2c0>;
enum-name = "I2C_PORT_ACCEL";
- label = "ACCEL";
};
i2c_sensor: sensor {
i2c-port = <&i2c1>;
enum-name = "I2C_PORT_SENSOR";
- label = "SENSOR";
};
};
@@ -157,6 +154,35 @@
};
};
+ cbi-fw-config {
+ compatible = "named-cbi-fw-config";
+ field-1 {
+ enum-name = "FW_CONFIG_FIELD_1";
+ start = <0>;
+ size = <2>;
+ val-0 {
+ compatible = "named-cbi-fw-config-value";
+ enum-name = "FW_FIELD_1_A";
+ value = <0>;
+ };
+ val-1 {
+ compatible = "named-cbi-fw-config-value";
+ enum-name = "FW_FIELD_1_B";
+ value = <1>;
+ };
+ };
+ field-2 {
+ enum-name = "FW_CONFIG_FIELD_2";
+ start = <5>;
+ size = <1>;
+ val-1 {
+ compatible = "named-cbi-fw-config-value";
+ enum-name = "FW_FIELD_2_X";
+ value = <1>;
+ };
+ };
+ };
+
adc0: adc {
compatible = "zephyr,adc-emul";
nchannels = <4>;
@@ -195,7 +221,7 @@
charger {
thermistor = <&thermistor_3V3_13K7_47K_4050B>;
status = "okay";
- compatible = "cros-ec,temp-sensor";
+ compatible = "cros-ec,temp-sensor-thermistor";
label = "TEMP_SENSOR_CHARGER";
enum-name = "TEMP_SENSOR_CHARGER";
temp_fan_off = <40>;
@@ -208,7 +234,7 @@
pp3300-regulator {
thermistor = <&thermistor_3V3_30K9_47K_4050B>;
status = "okay";
- compatible = "cros-ec,temp-sensor";
+ compatible = "cros-ec,temp-sensor-thermistor";
label = "TEMP_SENSOR_PP3300_REGULATOR";
enum-name = "TEMP_SENSOR_PP3300_REGULATOR";
temp_fan_off = <40>;
@@ -221,7 +247,7 @@
ddr-soc {
thermistor = <&thermistor_3V3_51K1_47K_4050B>;
status = "okay";
- compatible = "cros-ec,temp-sensor";
+ compatible = "cros-ec,temp-sensor-thermistor";
label = "TEMP_SENSOR_DDR_SOC";
enum-name = "TEMP_SENSOR_DDR_SOC";
temp_fan_off = <35>;
@@ -234,7 +260,7 @@
fan {
thermistor = <&thermistor_3V0_22K6_47K_4050B>;
status = "okay";
- compatible = "cros-ec,temp-sensor";
+ compatible = "cros-ec,temp-sensor-thermistor";
label = "TEMP_SENSOR_FAN";
enum-name = "TEMP_SENSOR_FAN";
temp_fan_off = <35>;
@@ -500,6 +526,7 @@
reg = <0x41>;
label = "SYV682X_EMUL";
frs_en_gpio = <&gpio_usb_c1_frs_en>;
+ alert_gpio = <&gpio_usb_c1_ppc_int>;
};
usb_c1_bb_retimer_emul: bbretimer@42 {
@@ -539,7 +566,7 @@
};
&gpio0 {
- ngpios = <13>;
+ ngpios = <16>;
};
&i2c0 {
@@ -582,6 +609,7 @@
compatible = "cros,sn5s330-emul";
reg = <0x40>;
label = "SN5S330_EMUL";
+ int_gpio = <&gpio_usb_c0_ppc_int>;
};
accel_bmi260: bmi260@68 {
@@ -600,6 +628,7 @@
status = "okay";
reg = <0x80>;
label = "LN9310";
+ pg_int_gpio = <&gpio_switchcap_pg_int_l>;
};
lis2dw12_emul: lis2dw12@19 {
@@ -621,6 +650,7 @@
status = "okay";
reg = <0x9>;
label = "ISL923X_EMUL";
+ battery = <&battery>;
};
tcpci_emul: tcpci_emul@82 {
diff --git a/zephyr/test/drivers/prj.conf b/zephyr/test/drivers/prj.conf
index ed41ea5357..1d79c2a840 100644
--- a/zephyr/test/drivers/prj.conf
+++ b/zephyr/test/drivers/prj.conf
@@ -18,6 +18,7 @@ CONFIG_EXCEPTION_STACK_TRACE=y
CONFIG_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_OPTIMIZATIONS=y
+CONFIG_PLATFORM_EC_CONSOLE_DEBUG=y
CONFIG_PLATFORM_EC=y
CONFIG_CROS_EC=y
@@ -40,6 +41,10 @@ CONFIG_EMUL_BMI=y
CONFIG_EMUL_TCS3400=y
CONFIG_EMUL_BB_RETIMER=y
CONFIG_EMUL_PS8XXX=y
+CONFIG_EMUL_TCPCI_PARTNER_SRC=y
+CONFIG_EMUL_TCPCI_PARTNER_SNK=y
+CONFIG_PLATFORM_EC_CHARGE_MANAGER=y
+CONFIG_PLATFORM_EC_CHARGE_RAMP_SW=y
CONFIG_PLATFORM_EC_POWERSEQ=y
@@ -71,6 +76,7 @@ CONFIG_PLATFORM_EC_USBC_PPC_SN5S330=y
CONFIG_PLATFORM_EC_CBI_EEPROM=y
CONFIG_PLATFORM_EC_ADC=y
CONFIG_PLATFORM_EC_TEMP_SENSOR=y
+CONFIG_PLATFORM_EC_TEMP_SENSOR_POWER=y
CONFIG_PLATFORM_EC_THERMISTOR=y
CONFIG_PLATFORM_EC_SWITCHCAP_LN9310=y
CONFIG_PLATFORM_EC_ACCEL_BMA255=y
@@ -93,7 +99,6 @@ CONFIG_PLATFORM_EC_USB_PD_TCPM_MULTI_PS8XXX=y
CONFIG_ESPI=y
CONFIG_ESPI_EMUL=y
CONFIG_EMUL_ESPI_HOST=y
-CONFIG_PLATFORM_EC_ESPI=y
CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION=y
CONFIG_ESPI_PERIPHERAL_CUSTOM_OPCODE=y
CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD=y
diff --git a/zephyr/test/drivers/src/bb_retimer.c b/zephyr/test/drivers/src/bb_retimer.c
index 39af8da2c3..02a712aacb 100644
--- a/zephyr/test/drivers/src/bb_retimer.c
+++ b/zephyr/test/drivers/src/bb_retimer.c
@@ -441,13 +441,7 @@ static void test_bb_init(void)
emul = bb_emul_get(BB_RETIMER_ORD);
/* Set AP to normal state and wait for chipset task */
- set_mock_power_state(POWER_S0);
- /*
- * TODO(b/201420132) - setting power state requires to wake up
- * TASK_ID_CHIPSET Sleep is required to run chipset task before
- * continuing with test
- */
- k_msleep(1);
+ power_set_state(POWER_S0);
/* Setup emulator fail on read */
i2c_common_emul_set_read_fail_reg(emul, BB_RETIMER_REG_VENDOR_ID);
@@ -508,13 +502,7 @@ static void test_bb_init(void)
NULL);
/* Set AP to off state and wait for chipset task */
- set_mock_power_state(POWER_G3);
- /*
- * TODO(b/201420132) - setting power state requires to wake up
- * TASK_ID_CHIPSET Sleep is required to run chipset task before
- * continuing with test
- */
- k_msleep(1);
+ power_set_state(POWER_G3);
/* With AP off, init should fail and pins should be unset */
zassert_equal(EC_ERROR_NOT_POWERED,
diff --git a/zephyr/test/drivers/src/bmi160.c b/zephyr/test/drivers/src/bmi160.c
index 080ec2ab96..736077b523 100644
--- a/zephyr/test/drivers/src/bmi160.c
+++ b/zephyr/test/drivers/src/bmi160.c
@@ -1997,7 +1997,7 @@ static void test_bmi_interrupt_handler(void)
* interrupt, and ensure the flag is set.
*/
- uint32_t *mask;
+ atomic_t *mask;
mask = task_get_event_bitmap(TASK_ID_MOTIONSENSE);
zassert_true(mask != NULL,
diff --git a/zephyr/test/drivers/src/bmi260.c b/zephyr/test/drivers/src/bmi260.c
index fb00288367..fb33a4e888 100644
--- a/zephyr/test/drivers/src/bmi260.c
+++ b/zephyr/test/drivers/src/bmi260.c
@@ -1913,7 +1913,7 @@ void test_interrupt_handler(void)
* interrupt, and ensure the flag is set.
*/
- uint32_t *mask;
+ atomic_t *mask;
mask = task_get_event_bitmap(TASK_ID_MOTIONSENSE);
zassert_true(mask != NULL,
diff --git a/zephyr/test/drivers/src/cros_cbi.c b/zephyr/test/drivers/src/cros_cbi.c
index ee3666f3f0..5209bb2b7f 100644
--- a/zephyr/test/drivers/src/cros_cbi.c
+++ b/zephyr/test/drivers/src/cros_cbi.c
@@ -39,10 +39,32 @@ static void test_fail_check_match(void)
"Expected cbi ssfc to never match CBI_SSFC_VALUE_COUNT");
}
+static void test_fw_config(void)
+{
+ const struct device *dev = device_get_binding(CROS_CBI_LABEL);
+ uint32_t value;
+ int ret;
+
+ zassert_not_null(dev, NULL);
+
+ ret = cros_cbi_get_fw_config(dev, FW_CONFIG_FIELD_1, &value);
+ zassert_true(ret == 0,
+ "Expected no error return from cros_cbi_get_fw_config");
+ zassert_true(value == FW_FIELD_1_A,
+ "Expected field value to match FW_FIELD_1_A");
+
+ ret = cros_cbi_get_fw_config(dev, FW_CONFIG_FIELD_2, &value);
+ zassert_true(ret == 0,
+ "Expected no error return from cros_cbi_get_fw_config");
+ zassert_false(value == FW_FIELD_2_X,
+ "Expected field value to not match FW_FIELD_2_X");
+}
+
void test_suite_cros_cbi(void)
{
ztest_test_suite(cros_cbi,
ztest_unit_test(test_check_match),
- ztest_unit_test(test_fail_check_match));
+ ztest_unit_test(test_fail_check_match),
+ ztest_unit_test(test_fw_config));
ztest_run_test_suite(cros_cbi);
}
diff --git a/zephyr/test/drivers/src/espi.c b/zephyr/test/drivers/src/espi.c
index c852f1b771..81cbac30da 100644
--- a/zephyr/test/drivers/src/espi.c
+++ b/zephyr/test/drivers/src/espi.c
@@ -13,7 +13,8 @@ static void test_host_command_get_protocol_info(void)
{
struct ec_response_get_protocol_info response;
struct host_cmd_handler_args args =
- BUILD_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, 0, response);
+ BUILD_HOST_COMMAND_RESPONSE(EC_CMD_GET_PROTOCOL_INFO, 0,
+ response);
zassert_ok(host_command_process(&args), NULL);
zassert_ok(args.result, NULL);
diff --git a/zephyr/test/drivers/src/integration_usb.c b/zephyr/test/drivers/src/integration_usb.c
new file mode 100644
index 0000000000..c61a706002
--- /dev/null
+++ b/zephyr/test/drivers/src/integration_usb.c
@@ -0,0 +1,187 @@
+/* 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 <zephyr.h>
+#include <ztest.h>
+#include <drivers/gpio/gpio_emul.h>
+
+#include "battery_smart.h"
+#include "ec_commands.h"
+#include "ec_tasks.h"
+#include "emul/emul_smart_battery.h"
+#include "emul/tcpc/emul_tcpci.h"
+#include "emul/tcpc/emul_tcpci_partner_src.h"
+#include "host_command.h"
+#include "tcpm/tcpci.h"
+
+#define TCPCI_EMUL_LABEL DT_NODELABEL(tcpci_emul)
+#define BATTERY_ORD DT_DEP_ORD(DT_NODELABEL(battery))
+
+#define GPIO_AC_OK_PATH DT_PATH(named_gpios, acok_od)
+#define GPIO_AC_OK_PIN DT_GPIO_PIN(GPIO_AC_OK_PATH, gpios)
+
+static void init_tcpm(void)
+{
+ const struct emul *tcpci_emul =
+ emul_get_binding(DT_LABEL(TCPCI_EMUL_LABEL));
+ struct i2c_emul *i2c_emul;
+ struct sbat_emul_bat_data *bat;
+ const struct device *gpio_dev =
+ DEVICE_DT_GET(DT_GPIO_CTLR(GPIO_AC_OK_PATH, gpios));
+
+ set_test_runner_tid();
+ zassert_ok(tcpci_tcpm_init(0), 0);
+ pd_set_suspend(0, 0);
+ /* Reset to disconnected state. */
+ zassert_ok(tcpci_emul_disconnect_partner(tcpci_emul), NULL);
+
+ /* Battery defaults to charging, so reset to not charging. */
+ i2c_emul = sbat_emul_get_ptr(BATTERY_ORD);
+ bat = sbat_emul_get_bat_data(i2c_emul);
+ bat->cur = -5;
+
+ zassert_ok(gpio_emul_input_set(gpio_dev, GPIO_AC_OK_PIN, 0), NULL);
+}
+
+static void remove_emulated_devices(void)
+{
+ const struct emul *tcpci_emul =
+ emul_get_binding(DT_LABEL(TCPCI_EMUL_LABEL));
+ /* TODO: This function should trigger gpios to signal there is nothing
+ * attached to the port.
+ */
+ zassert_ok(tcpci_emul_disconnect_partner(tcpci_emul), NULL);
+}
+
+static void test_attach_compliant_charger(void)
+{
+ const struct emul *tcpci_emul =
+ emul_get_binding(DT_LABEL(TCPCI_EMUL_LABEL));
+ struct i2c_emul *i2c_emul;
+ uint16_t battery_status;
+ struct tcpci_src_emul_data my_charger;
+ const struct device *gpio_dev =
+ DEVICE_DT_GET(DT_GPIO_CTLR(GPIO_AC_OK_PATH, gpios));
+
+ /* Verify battery not charging. */
+ i2c_emul = sbat_emul_get_ptr(BATTERY_ORD);
+ zassert_ok(sbat_emul_get_word_val(i2c_emul, SB_BATTERY_STATUS,
+ &battery_status),
+ NULL);
+ zassert_not_equal(battery_status & STATUS_DISCHARGING, 0,
+ "Battery is not discharging: %d", battery_status);
+
+ /* TODO? Send host command to verify PD_ROLE_DISCONNECTED. */
+
+ /* Attach emulated charger. */
+ zassert_ok(gpio_emul_input_set(gpio_dev, GPIO_AC_OK_PIN, 1), NULL);
+ tcpci_src_emul_init(&my_charger);
+ zassert_ok(tcpci_src_emul_connect_to_tcpci(&my_charger, tcpci_emul),
+ NULL);
+
+ /* Wait for current ramp. */
+ k_sleep(K_SECONDS(10));
+
+ /* Verify battery charging. */
+ zassert_ok(sbat_emul_get_word_val(i2c_emul, SB_BATTERY_STATUS,
+ &battery_status),
+ NULL);
+ zassert_equal(battery_status & STATUS_DISCHARGING, 0,
+ "Battery is discharging: %d", battery_status);
+ /* TODO: Also check voltage, current, etc. */
+}
+
+static void test_attach_pd_charger(void)
+{
+ const struct emul *tcpci_emul =
+ emul_get_binding(DT_LABEL(TCPCI_EMUL_LABEL));
+ struct i2c_emul *i2c_emul;
+ uint16_t battery_status;
+ struct tcpci_src_emul_data my_charger;
+ const struct device *gpio_dev =
+ DEVICE_DT_GET(DT_GPIO_CTLR(GPIO_AC_OK_PATH, gpios));
+ struct ec_params_charge_state charge_params;
+ struct ec_response_charge_state charge_response;
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND(
+ EC_CMD_CHARGE_STATE, 0, charge_response, charge_params);
+
+ /*
+ * TODO(b/209907297): Implement the steps of the test beyond USB default
+ * charging.
+ */
+
+ /* 1. Configure source PDOs of partner (probably fixed source 5V 3A
+ * and fixed source 20V 3A). Currently, the partner emulator only
+ * supports the default USB power PDO.
+ */
+
+ /* Attach emulated charger. This will send Source Capabilities. */
+ zassert_ok(gpio_emul_input_set(gpio_dev, GPIO_AC_OK_PIN, 1), NULL);
+ tcpci_src_emul_init(&my_charger);
+ zassert_ok(tcpci_src_emul_connect_to_tcpci(&my_charger, tcpci_emul),
+ NULL);
+
+ /* Wait for current ramp. */
+ k_sleep(K_SECONDS(10));
+
+ /* Verify battery charging. */
+ i2c_emul = sbat_emul_get_ptr(BATTERY_ORD);
+ zassert_ok(sbat_emul_get_word_val(i2c_emul, SB_BATTERY_STATUS,
+ &battery_status),
+ NULL);
+ zassert_equal(battery_status & STATUS_DISCHARGING, 0,
+ "Battery is discharging: %d", battery_status);
+
+ /*
+ * 2. Check charging current and voltage (should be 5V, default USB
+ * current); make sure that reports from battery and PD host commands
+ * match; check that host command reports no active PDO.
+ */
+ /*
+ * TODO(b/209907297): Also check the corresponding PD state and
+ * encapsulate this for use in other tests.
+ */
+ charge_params.chgnum = 0;
+ charge_params.cmd = CHARGE_STATE_CMD_GET_STATE;
+ zassert_ok(host_command_process(&args), "Failed to get charge state");
+ zassert_true(charge_response.get_state.ac, "USB default but AC absent");
+ zassert_equal(charge_response.get_state.chg_voltage, 5000,
+ "USB default volage %dmV",
+ charge_response.get_state.chg_voltage);
+ zassert_true(charge_response.get_state.chg_current > 0,
+ "USB default current %dmA",
+ charge_response.get_state.chg_current);
+
+ /*
+ * 3. Wait for SenderResponseTimeout. Expect TCPM to send Request.
+ * We could verify that the Request references the expected PDO, but
+ * the voltage/current/PDO checks at the end of the test should all be
+ * wrong if the requested PDO was wrong here.
+ */
+
+ /*
+ * 4. Send Accept and PS_RDY from partner with appropriate delay between
+ * them. Emulate supplying VBUS at the requested voltage/current before
+ * PS_RDY.
+ */
+
+ /*
+ * 5. Check the charging voltage and current. Cross-check the PD state,
+ * the battery/charger state, and the active PDO as reported by the PD
+ * state.
+ */
+}
+
+void test_suite_integration_usb(void)
+{
+ ztest_test_suite(integration_usb,
+ ztest_user_unit_test_setup_teardown(
+ test_attach_compliant_charger, init_tcpm,
+ remove_emulated_devices),
+ ztest_user_unit_test_setup_teardown(
+ test_attach_pd_charger, init_tcpm,
+ remove_emulated_devices));
+ ztest_run_test_suite(integration_usb);
+}
diff --git a/zephyr/test/drivers/src/isl923x.c b/zephyr/test/drivers/src/isl923x.c
index e1b1dbc020..27ce29984a 100644
--- a/zephyr/test/drivers/src/isl923x.c
+++ b/zephyr/test/drivers/src/isl923x.c
@@ -5,6 +5,7 @@
#include <ztest.h>
#include <drivers/emul.h>
+#include <fff.h>
#include "battery.h"
#include "battery_smart.h"
@@ -14,6 +15,7 @@
#include "emul/emul_common_i2c.h"
#include "emul/emul_isl923x.h"
#include "system.h"
+#include "test_mocks.h"
BUILD_ASSERT(CONFIG_CHARGER_SENSE_RESISTOR == 10 ||
CONFIG_CHARGER_SENSE_RESISTOR == 5);
@@ -673,24 +675,451 @@ static void test_init(void)
system_jumped_late_mock.ret_val = false;
}
+static void test_isl923x_is_acok(void)
+{
+ const struct emul *isl923x_emul = ISL923X_EMUL;
+ struct i2c_emul *i2c_emul = isl923x_emul_get_i2c_emul(isl923x_emul);
+ enum ec_error_list rv;
+ bool acok;
+
+ /* Part 1: invalid charger number */
+ rv = raa489000_is_acok(board_get_charger_chip_count() + 1, &acok);
+ zassert_equal(EC_ERROR_INVAL, rv,
+ "Invalid charger num, but AC OK check succeeded");
+
+ /* Part 2: error accessing register */
+ i2c_common_emul_set_read_fail_reg(i2c_emul, ISL9238_REG_INFO2);
+
+ rv = raa489000_is_acok(CHARGER_NUM, &acok);
+ zassert_equal(EC_ERROR_INVAL, rv,
+ "Register read failure, but AC OK check succeeded");
+
+ i2c_common_emul_set_read_fail_reg(i2c_emul,
+ I2C_COMMON_EMUL_NO_FAIL_REG);
+
+ /* Part 3: successful path - ACOK is true */
+ raa489000_emul_set_acok_pin(isl923x_emul, 1);
+
+ rv = raa489000_is_acok(CHARGER_NUM, &acok);
+ zassert_equal(EC_SUCCESS, rv, "AC OK check did not return success");
+ zassert_true(acok, "AC OK is false");
+
+ /* Part 3: successful path - ACOK is false */
+ raa489000_emul_set_acok_pin(isl923x_emul, 0);
+
+ rv = raa489000_is_acok(CHARGER_NUM, &acok);
+ zassert_equal(EC_SUCCESS, rv, "AC OK check did not return success");
+ zassert_false(acok, "AC OK is true");
+}
+
+static void test_isl923x_enable_asgate(void)
+{
+ const struct emul *isl923x_emul = ISL923X_EMUL;
+ struct i2c_emul *i2c_emul = isl923x_emul_get_i2c_emul(isl923x_emul);
+ int rv;
+
+ /* Part 1: Try enabling the ASGATE */
+ rv = raa489000_enable_asgate(CHARGER_NUM, true);
+
+ zassert_equal(EC_SUCCESS, rv, "Expected return code of %d but got %d",
+ EC_SUCCESS, rv);
+ zassert_true(
+ isl923x_emul_peek_reg(i2c_emul, RAA489000_REG_CONTROL8) &
+ RAA489000_C8_ASGATE_ON_READY,
+ "RAA489000_C8_ASGATE_ON_READY bit not set in Control Reg 8");
+
+ /* Part 2: Turn it back off */
+ rv = raa489000_enable_asgate(CHARGER_NUM, false);
+
+ zassert_equal(EC_SUCCESS, rv, "Expected return code of %d but got %d",
+ EC_SUCCESS, rv);
+ zassert_false(isl923x_emul_peek_reg(i2c_emul, RAA489000_REG_CONTROL8) &
+ RAA489000_C8_ASGATE_ON_READY,
+ "RAA489000_C8_ASGATE_ON_READY bit set in Control Reg 8");
+}
+
+/* Mock read and write functions to use in the hibernation test */
+FAKE_VALUE_FUNC(int, hibernate_mock_read_fn, struct i2c_emul *, int, uint8_t *,
+ int, void *);
+FAKE_VALUE_FUNC(int, hibernate_mock_write_fn, struct i2c_emul *, int, uint8_t,
+ int, void *);
+
+/**
+ * @brief Setup function for the hibernate tests.
+ */
+static void hibernate_test_setup(void)
+{
+ const struct emul *isl923x_emul = ISL923X_EMUL;
+ struct i2c_emul *i2c_emul = isl923x_emul_get_i2c_emul(isl923x_emul);
+
+ /* Reset mocks and make the read/write mocks pass all data through */
+ RESET_FAKE(hibernate_mock_read_fn);
+ RESET_FAKE(hibernate_mock_write_fn);
+ hibernate_mock_read_fn_fake.return_val = 1;
+ hibernate_mock_write_fn_fake.return_val = 1;
+
+ i2c_common_emul_set_read_func(i2c_emul, hibernate_mock_read_fn, NULL);
+ i2c_common_emul_set_write_func(i2c_emul, hibernate_mock_write_fn, NULL);
+
+ /* Don't fail on any register access */
+ i2c_common_emul_set_read_fail_reg(i2c_emul,
+ I2C_COMMON_EMUL_NO_FAIL_REG);
+ i2c_common_emul_set_write_fail_reg(i2c_emul,
+ I2C_COMMON_EMUL_NO_FAIL_REG);
+}
+
+/**
+ * @brief Teardown function for the hibernate tests.
+ */
+static void hibernate_test_teardown(void)
+{
+ const struct emul *isl923x_emul = ISL923X_EMUL;
+ struct i2c_emul *i2c_emul = isl923x_emul_get_i2c_emul(isl923x_emul);
+
+ /* Clear the mock read/write functions */
+ i2c_common_emul_set_read_func(i2c_emul, NULL, NULL);
+ i2c_common_emul_set_write_func(i2c_emul, NULL, NULL);
+
+ /* Don't fail on any register access */
+ i2c_common_emul_set_read_fail_reg(i2c_emul,
+ I2C_COMMON_EMUL_NO_FAIL_REG);
+ i2c_common_emul_set_write_fail_reg(i2c_emul,
+ I2C_COMMON_EMUL_NO_FAIL_REG);
+}
+
+static void test_isl923x_hibernate__happy_path(void)
+{
+ const struct emul *isl923x_emul = ISL923X_EMUL;
+ struct i2c_emul *i2c_emul = isl923x_emul_get_i2c_emul(isl923x_emul);
+ uint16_t actual;
+
+ raa489000_hibernate(CHARGER_NUM, false);
+
+ /* Check ISL923X_REG_CONTROL0 */
+ actual = isl923x_emul_peek_reg(i2c_emul, ISL923X_REG_CONTROL0);
+
+ zassert_false(actual & RAA489000_C0_EN_CHG_PUMPS_TO_100PCT,
+ "RAA489000_C0_EN_CHG_PUMPS_TO_100PCT should not be set");
+ zassert_false(actual & RAA489000_C0_BGATE_FORCE_ON,
+ "RAA489000_C0_BGATE_FORCE_ON should not be set");
+
+ /* Check ISL923X_REG_CONTROL1 */
+ actual = isl923x_emul_peek_reg(i2c_emul, ISL923X_REG_CONTROL1);
+
+ zassert_false(actual & RAA489000_C1_ENABLE_SUPP_SUPPORT_MODE,
+ "RAA489000_C1_ENABLE_SUPP_SUPPORT_MODE should not be set");
+ zassert_false(actual & ISL923X_C1_ENABLE_PSYS,
+ "ISL923X_C1_ENABLE_PSYS should not be set");
+ zassert_true(actual & RAA489000_C1_BGATE_FORCE_OFF,
+ "RAA489000_C1_BGATE_FORCE_OFF should be set");
+ zassert_true(actual & ISL923X_C1_DISABLE_MON,
+ "ISL923X_C1_DISABLE_MON should be set");
+
+ /* Check ISL9238_REG_CONTROL3 (disable_adc = false) */
+ actual = isl923x_emul_peek_reg(i2c_emul, ISL9238_REG_CONTROL3);
+
+ zassert_true(actual & RAA489000_ENABLE_ADC,
+ "RAA489000_ENABLE_ADC should be set");
+
+ /* Check ISL9238_REG_CONTROL4 */
+ actual = isl923x_emul_peek_reg(i2c_emul, ISL9238_REG_CONTROL4);
+
+ zassert_true(actual & RAA489000_C4_DISABLE_GP_CMP,
+ "RAA489000_C4_DISABLE_GP_CMP should be set");
+
+ /* Ensure all expected register reads and writes happened */
+ int registers[] = { ISL923X_REG_CONTROL0, ISL923X_REG_CONTROL1,
+ ISL9238_REG_CONTROL3, ISL9238_REG_CONTROL4 };
+
+ for (int i = 0; i < ARRAY_SIZE(registers); i++) {
+ /* Each reg has 2 reads and 2 writes because they are 16-bit */
+ MOCK_ASSERT_I2C_READ(hibernate_mock_read_fn, i * 2,
+ registers[i]);
+ MOCK_ASSERT_I2C_READ(hibernate_mock_read_fn, (i * 2) + 1,
+ registers[i]);
+ MOCK_ASSERT_I2C_WRITE(hibernate_mock_write_fn, i * 2,
+ registers[i], MOCK_IGNORE_VALUE);
+ MOCK_ASSERT_I2C_WRITE(hibernate_mock_write_fn, (i * 2) + 1,
+ registers[i], MOCK_IGNORE_VALUE);
+ }
+}
+
+static void test_isl923x_hibernate__invalid_charger_number(void)
+{
+ /* Mocks should just be pass-through */
+ RESET_FAKE(hibernate_mock_read_fn);
+ RESET_FAKE(hibernate_mock_write_fn);
+ hibernate_mock_read_fn_fake.return_val = 1;
+ hibernate_mock_write_fn_fake.return_val = 1;
+
+ raa489000_hibernate(board_get_charger_chip_count() + 1, false);
+
+ /* Make sure no I2C activity happened */
+ zassert_equal(hibernate_mock_read_fn_fake.call_count, 0,
+ "No I2C reads should have happened");
+ zassert_equal(hibernate_mock_write_fn_fake.call_count, 0,
+ "No I2C writes should have happened");
+}
+
+static void test_isl923x_hibernate__fail_at_ISL923X_REG_CONTROL0(void)
+{
+ const struct emul *isl923x_emul = ISL923X_EMUL;
+ struct i2c_emul *i2c_emul = isl923x_emul_get_i2c_emul(isl923x_emul);
+
+ i2c_common_emul_set_read_fail_reg(i2c_emul, ISL923X_REG_CONTROL0);
+
+ raa489000_hibernate(CHARGER_NUM, false);
+
+ /*
+ * We have no return codes to check, so instead verify that the first
+ * successful I2C write is to CONTROL1 and not CONTROL0.
+ */
+
+ MOCK_ASSERT_I2C_WRITE(hibernate_mock_write_fn, 0, ISL923X_REG_CONTROL1,
+ MOCK_IGNORE_VALUE);
+}
+
+static void test_isl923x_hibernate__fail_at_ISL923X_REG_CONTROL1(void)
+{
+ const struct emul *isl923x_emul = ISL923X_EMUL;
+ struct i2c_emul *i2c_emul = isl923x_emul_get_i2c_emul(isl923x_emul);
+
+ i2c_common_emul_set_read_fail_reg(i2c_emul, ISL923X_REG_CONTROL1);
+
+ raa489000_hibernate(CHARGER_NUM, false);
+
+ /*
+ * Ensure we skipped CONTROL1. (NB: due to 16-bit regs, each write takes
+ * two calls to the mock_write_fn)
+ */
+
+ MOCK_ASSERT_I2C_WRITE(hibernate_mock_write_fn, 0, ISL923X_REG_CONTROL0,
+ MOCK_IGNORE_VALUE);
+ MOCK_ASSERT_I2C_WRITE(hibernate_mock_write_fn, 1, ISL923X_REG_CONTROL0,
+ MOCK_IGNORE_VALUE);
+ MOCK_ASSERT_I2C_WRITE(hibernate_mock_write_fn, 2, ISL9238_REG_CONTROL3,
+ MOCK_IGNORE_VALUE);
+ MOCK_ASSERT_I2C_WRITE(hibernate_mock_write_fn, 3, ISL9238_REG_CONTROL3,
+ MOCK_IGNORE_VALUE);
+}
+
+static void test_isl923x_hibernate__fail_at_ISL9238_REG_CONTROL3(void)
+{
+ const struct emul *isl923x_emul = ISL923X_EMUL;
+ struct i2c_emul *i2c_emul = isl923x_emul_get_i2c_emul(isl923x_emul);
+
+ i2c_common_emul_set_read_fail_reg(i2c_emul, ISL9238_REG_CONTROL3);
+
+ raa489000_hibernate(CHARGER_NUM, false);
+
+ /*
+ * Ensure we skipped CONTROL3. (NB: due to 16-bit regs, each write takes
+ * two calls to the mock_write_fn)
+ */
+
+ MOCK_ASSERT_I2C_WRITE(hibernate_mock_write_fn, 2, ISL923X_REG_CONTROL1,
+ MOCK_IGNORE_VALUE);
+ MOCK_ASSERT_I2C_WRITE(hibernate_mock_write_fn, 3, ISL923X_REG_CONTROL1,
+ MOCK_IGNORE_VALUE);
+ MOCK_ASSERT_I2C_WRITE(hibernate_mock_write_fn, 4, ISL9238_REG_CONTROL4,
+ MOCK_IGNORE_VALUE);
+ MOCK_ASSERT_I2C_WRITE(hibernate_mock_write_fn, 5, ISL9238_REG_CONTROL4,
+ MOCK_IGNORE_VALUE);
+}
+
+static void test_isl923x_hibernate__fail_at_ISL9238_REG_CONTROL4(void)
+{
+ const struct emul *isl923x_emul = ISL923X_EMUL;
+ struct i2c_emul *i2c_emul = isl923x_emul_get_i2c_emul(isl923x_emul);
+
+ i2c_common_emul_set_read_fail_reg(i2c_emul, ISL9238_REG_CONTROL4);
+
+ raa489000_hibernate(CHARGER_NUM, false);
+
+ /*
+ * Ensure we skipped CONTROL4. (i.e. the last calls should be to write
+ * to CONTROL3)
+ */
+ MOCK_ASSERT_I2C_WRITE(hibernate_mock_write_fn,
+ hibernate_mock_write_fn_fake.call_count - 2,
+ ISL9238_REG_CONTROL3, MOCK_IGNORE_VALUE);
+ MOCK_ASSERT_I2C_WRITE(hibernate_mock_write_fn,
+ hibernate_mock_write_fn_fake.call_count - 1,
+ ISL9238_REG_CONTROL3, MOCK_IGNORE_VALUE);
+}
+
+static void test_isl923x_hibernate__adc_disable(void)
+{
+ const struct emul *isl923x_emul = ISL923X_EMUL;
+ struct i2c_emul *i2c_emul = isl923x_emul_get_i2c_emul(isl923x_emul);
+ uint16_t expected;
+
+ raa489000_hibernate(CHARGER_NUM, true);
+
+ /* Check ISL9238_REG_CONTROL3 (disable_adc = true) */
+ expected = isl923x_emul_peek_reg(i2c_emul, ISL9238_REG_CONTROL3);
+ expected &= ~RAA489000_ENABLE_ADC;
+
+ MOCK_ASSERT_I2C_READ(hibernate_mock_read_fn, 4, ISL9238_REG_CONTROL3);
+ MOCK_ASSERT_I2C_READ(hibernate_mock_read_fn, 5, ISL9238_REG_CONTROL3);
+ MOCK_ASSERT_I2C_WRITE(hibernate_mock_write_fn, 4, ISL9238_REG_CONTROL3,
+ expected & 0xff);
+ MOCK_ASSERT_I2C_WRITE(hibernate_mock_write_fn, 5, ISL9238_REG_CONTROL3,
+ expected >> 8);
+}
+
+static void test_isl9238c_hibernate(void)
+{
+ const struct emul *isl923x_emul = ISL923X_EMUL;
+ struct i2c_emul *i2c_emul = isl923x_emul_get_i2c_emul(isl923x_emul);
+ uint16_t control1_expected, control2_expected, control3_expected;
+ int rv;
+
+ /* Part 1: Happy path */
+ control1_expected =
+ (isl923x_emul_peek_reg(i2c_emul, ISL923X_REG_CONTROL1) &
+ ~ISL923X_C1_ENABLE_PSYS) |
+ ISL923X_C1_DISABLE_MON;
+ control2_expected =
+ isl923x_emul_peek_reg(i2c_emul, ISL923X_REG_CONTROL2) |
+ ISL923X_C2_COMPARATOR;
+ control3_expected =
+ isl923x_emul_peek_reg(i2c_emul, ISL9238_REG_CONTROL3) |
+ ISL9238_C3_BGATE_OFF;
+
+ rv = isl9238c_hibernate(CHARGER_NUM);
+
+ zassert_equal(EC_SUCCESS, rv, "Expected return code %d but got %d",
+ EC_SUCCESS, rv);
+ zassert_equal(isl923x_emul_peek_reg(i2c_emul, ISL923X_REG_CONTROL1),
+ control1_expected,
+ "Unexpected register value 0x%02x. Should be 0x%02x",
+ isl923x_emul_peek_reg(i2c_emul, ISL923X_REG_CONTROL1),
+ control1_expected);
+ zassert_equal(isl923x_emul_peek_reg(i2c_emul, ISL923X_REG_CONTROL2),
+ control2_expected,
+ "Unexpected register value 0x%02x. Should be 0x%02x",
+ isl923x_emul_peek_reg(i2c_emul, ISL923X_REG_CONTROL2),
+ control2_expected);
+ zassert_equal(isl923x_emul_peek_reg(i2c_emul, ISL9238_REG_CONTROL3),
+ control3_expected,
+ "Unexpected register value 0x%02x. Should be 0x%02x",
+ isl923x_emul_peek_reg(i2c_emul, ISL9238_REG_CONTROL3),
+ control3_expected);
+
+ /* Part 2: Fail reading each register and check for error code */
+ int registers[] = { ISL923X_REG_CONTROL1, ISL923X_REG_CONTROL2,
+ ISL9238_REG_CONTROL3 };
+
+ for (int i = 0; i < ARRAY_SIZE(registers); i++) {
+ i2c_common_emul_set_read_fail_reg(i2c_emul, registers[i]);
+
+ rv = isl9238c_hibernate(CHARGER_NUM);
+
+ zassert_equal(EC_ERROR_INVAL, rv,
+ "Wrong return code. Expected %d but got %d",
+ EC_ERROR_INVAL, rv);
+ }
+}
+
+static void test_isl9238c_resume(void)
+{
+ const struct emul *isl923x_emul = ISL923X_EMUL;
+ struct i2c_emul *i2c_emul = isl923x_emul_get_i2c_emul(isl923x_emul);
+ uint16_t control1_expected, control2_expected, control3_expected;
+ int rv;
+
+ /* Part 1: Happy path */
+ control1_expected =
+ (isl923x_emul_peek_reg(i2c_emul, ISL923X_REG_CONTROL1) &
+ ~ISL923X_C1_DISABLE_MON) | ISL923X_C1_ENABLE_PSYS
+ ;
+ control2_expected =
+ isl923x_emul_peek_reg(i2c_emul, ISL923X_REG_CONTROL2) &
+ ~ISL923X_C2_COMPARATOR;
+ control3_expected =
+ isl923x_emul_peek_reg(i2c_emul, ISL9238_REG_CONTROL3) &
+ ~ISL9238_C3_BGATE_OFF;
+
+ rv = isl9238c_resume(CHARGER_NUM);
+
+ zassert_equal(EC_SUCCESS, rv, "Expected return code %d but got %d",
+ EC_SUCCESS, rv);
+ zassert_equal(isl923x_emul_peek_reg(i2c_emul, ISL923X_REG_CONTROL1),
+ control1_expected,
+ "Unexpected register value 0x%02x. Should be 0x%02x",
+ isl923x_emul_peek_reg(i2c_emul, ISL923X_REG_CONTROL1),
+ control1_expected);
+ zassert_equal(isl923x_emul_peek_reg(i2c_emul, ISL923X_REG_CONTROL2),
+ control2_expected,
+ "Unexpected register value 0x%02x. Should be 0x%02x",
+ isl923x_emul_peek_reg(i2c_emul, ISL923X_REG_CONTROL2),
+ control2_expected);
+ zassert_equal(isl923x_emul_peek_reg(i2c_emul, ISL9238_REG_CONTROL3),
+ control3_expected,
+ "Unexpected register value 0x%02x. Should be 0x%02x",
+ isl923x_emul_peek_reg(i2c_emul, ISL9238_REG_CONTROL3),
+ control3_expected);
+
+ /* Part 2: Fail reading each register and check for error code */
+ int registers[] = { ISL923X_REG_CONTROL1, ISL923X_REG_CONTROL2,
+ ISL9238_REG_CONTROL3 };
+
+ for (int i = 0; i < ARRAY_SIZE(registers); i++) {
+ i2c_common_emul_set_read_fail_reg(i2c_emul, registers[i]);
+
+ rv = isl9238c_resume(CHARGER_NUM);
+
+ zassert_equal(EC_ERROR_INVAL, rv,
+ "Wrong return code. Expected %d but got %d",
+ EC_ERROR_INVAL, rv);
+ }
+}
+
void test_suite_isl923x(void)
{
- ztest_test_suite(isl923x,
- ztest_unit_test(test_isl923x_set_current),
- ztest_unit_test(test_isl923x_set_voltage),
- ztest_unit_test(test_isl923x_set_input_current_limit),
- ztest_unit_test(test_manufacturer_id),
- ztest_unit_test(test_device_id),
- ztest_unit_test(test_options),
- ztest_unit_test(test_get_info),
- ztest_unit_test(test_status),
- ztest_unit_test(test_set_mode),
- ztest_unit_test(test_post_init),
- ztest_unit_test(test_set_ac_prochot),
- ztest_unit_test(test_set_dc_prochot),
- ztest_unit_test(test_comparator_inversion),
- ztest_unit_test(test_discharge_on_ac),
- ztest_unit_test(test_get_vbus_voltage),
- ztest_unit_test(test_init));
+ ztest_test_suite(
+ isl923x, ztest_unit_test(test_isl923x_set_current),
+ ztest_unit_test(test_isl923x_set_voltage),
+ ztest_unit_test(test_isl923x_set_input_current_limit),
+ ztest_unit_test(test_manufacturer_id),
+ ztest_unit_test(test_device_id), ztest_unit_test(test_options),
+ ztest_unit_test(test_get_info), ztest_unit_test(test_status),
+ ztest_unit_test(test_set_mode), ztest_unit_test(test_post_init),
+ ztest_unit_test(test_set_ac_prochot),
+ ztest_unit_test(test_set_dc_prochot),
+ ztest_unit_test(test_comparator_inversion),
+ ztest_unit_test(test_discharge_on_ac),
+ ztest_unit_test(test_get_vbus_voltage),
+ ztest_unit_test(test_init),
+ ztest_unit_test(test_isl923x_is_acok),
+ ztest_unit_test(test_isl923x_enable_asgate),
+ ztest_unit_test_setup_teardown(
+ test_isl923x_hibernate__happy_path,
+ hibernate_test_setup, hibernate_test_teardown),
+ ztest_unit_test_setup_teardown(
+ test_isl923x_hibernate__invalid_charger_number,
+ hibernate_test_setup, hibernate_test_teardown),
+ ztest_unit_test_setup_teardown(
+ test_isl923x_hibernate__fail_at_ISL923X_REG_CONTROL0,
+ hibernate_test_setup, hibernate_test_teardown),
+ ztest_unit_test_setup_teardown(
+ test_isl923x_hibernate__fail_at_ISL923X_REG_CONTROL1,
+ hibernate_test_setup, hibernate_test_teardown),
+ ztest_unit_test_setup_teardown(
+ test_isl923x_hibernate__fail_at_ISL9238_REG_CONTROL3,
+ hibernate_test_setup, hibernate_test_teardown),
+ ztest_unit_test_setup_teardown(
+ test_isl923x_hibernate__fail_at_ISL9238_REG_CONTROL4,
+ hibernate_test_setup, hibernate_test_teardown),
+ ztest_unit_test_setup_teardown(
+ test_isl923x_hibernate__adc_disable,
+ hibernate_test_setup, hibernate_test_teardown),
+ ztest_unit_test_setup_teardown(test_isl9238c_hibernate,
+ hibernate_test_teardown,
+ hibernate_test_teardown),
+ ztest_unit_test_setup_teardown(test_isl9238c_resume,
+ hibernate_test_teardown,
+ hibernate_test_teardown));
ztest_run_test_suite(isl923x);
}
diff --git a/zephyr/test/drivers/src/lis2dw12.c b/zephyr/test/drivers/src/lis2dw12.c
index 287430e65b..24218aea9f 100644
--- a/zephyr/test/drivers/src/lis2dw12.c
+++ b/zephyr/test/drivers/src/lis2dw12.c
@@ -14,9 +14,34 @@
#define EMUL_LABEL DT_LABEL(DT_NODELABEL(lis2dw12_emul))
#include <stdio.h>
+
+#define CHECK_XYZ_EQUALS(VEC1, VEC2) \
+ do { \
+ zassert_equal((VEC1)[X], (VEC2)[X], \
+ "Got %d for X, expected %d", (VEC1)[X], \
+ (VEC2)[X]); \
+ zassert_equal((VEC1)[Y], (VEC2)[Y], \
+ "Got %d for Y, expected %d", (VEC1)[Y], \
+ (VEC2)[Y]); \
+ zassert_equal((VEC1)[Z], (VEC2)[Z], \
+ "Got %d for Z, expected %d", (VEC1)[Z], \
+ (VEC2)[Z]); \
+ } while (0)
+
+/** Used with the LIS2DW12 set rate function to control rounding behavior */
+enum lis2dw12_round_mode {
+ ROUND_DOWN,
+ ROUND_UP,
+};
+
static void lis2dw12_setup(void)
{
lis2dw12_emul_reset(emul_get_binding(EMUL_LABEL));
+
+ /* Reset certain sensor struct values */
+ struct motion_sensor_t *ms = &motion_sensors[LIS2DW12_SENSOR_ID];
+
+ ms->current_range = 0;
}
static void test_lis2dw12_init__fail_read_who_am_i(void)
@@ -97,23 +122,351 @@ static void test_lis2dw12_init__fail_set_bdu(void)
"expected at least one soft reset");
}
+static void test_lis2dw12_init__fail_set_lir(void)
+{
+ const struct emul *emul = emul_get_binding(EMUL_LABEL);
+ struct motion_sensor_t *ms = &motion_sensors[LIS2DW12_SENSOR_ID];
+ int rv;
+
+ i2c_common_emul_set_read_fail_reg(lis2dw12_emul_to_i2c_emul(emul),
+ LIS2DW12_LIR_ADDR);
+
+ rv = ms->drv->init(ms);
+ zassert_equal(EC_ERROR_INVAL, rv, "init returned %d but expected %d",
+ rv, EC_ERROR_INVAL);
+ zassert_true(lis2dw12_emul_get_soft_reset_count(emul) > 0,
+ "expected at least one soft reset");
+}
+
+static int lis2dw12_test_mock_write_fail_set_power_mode(struct i2c_emul *emul,
+ int reg, uint8_t val,
+ int bytes, void *data)
+{
+ if (reg == LIS2DW12_ACC_LPMODE_ADDR && bytes == 1 &&
+ (val & LIS2DW12_ACC_LPMODE_MASK) != 0) {
+ /* Cause an error when trying to set the LPMODE */
+ return -EIO;
+ }
+ return 1;
+}
+
+static void test_lis2dw12_init__fail_set_power_mode(void)
+{
+ const struct emul *emul = emul_get_binding(EMUL_LABEL);
+ struct motion_sensor_t *ms = &motion_sensors[LIS2DW12_SENSOR_ID];
+ int rv;
+
+ i2c_common_emul_set_write_func(
+ lis2dw12_emul_to_i2c_emul(emul),
+ lis2dw12_test_mock_write_fail_set_power_mode, NULL);
+
+ rv = ms->drv->init(ms);
+ zassert_equal(EC_ERROR_INVAL, rv, "init returned %d but expected %d",
+ rv, EC_ERROR_INVAL);
+ zassert_true(lis2dw12_emul_get_soft_reset_count(emul) > 0,
+ "expected at least one soft reset");
+}
+
+static void test_lis2dw12_init__success(void)
+{
+ const struct emul *emul = emul_get_binding(EMUL_LABEL);
+ struct motion_sensor_t *ms = &motion_sensors[LIS2DW12_SENSOR_ID];
+ struct stprivate_data *drvdata = ms->drv_data;
+
+ int rv;
+
+ rv = ms->drv->init(ms);
+ zassert_equal(EC_SUCCESS, rv, "init returned %d but expected %d", rv,
+ EC_SUCCESS);
+ zassert_true(lis2dw12_emul_get_soft_reset_count(emul) > 0,
+ "expected at least one soft reset");
+ zassert_equal(LIS2DW12_RESOLUTION, drvdata->resol,
+ "Expected resolution of %d but got %d",
+ LIS2DW12_RESOLUTION, drvdata->resol);
+}
+
+static void test_lis2dw12_set_power_mode(void)
+{
+ const struct emul *emul = emul_get_binding(EMUL_LABEL);
+ struct motion_sensor_t *ms = &motion_sensors[LIS2DW12_SENSOR_ID];
+ int rv;
+
+ /* Part 1: happy path */
+ rv = lis2dw12_set_power_mode(ms, LIS2DW12_LOW_POWER,
+ LIS2DW12_LOW_POWER_MODE_2);
+ zassert_equal(rv, EC_SUCCESS, "Expected %d but got %d", EC_SUCCESS, rv);
+
+ /* Part 2: unimplemented modes */
+ rv = lis2dw12_set_power_mode(ms, LIS2DW12_LOW_POWER,
+ LIS2DW12_LOW_POWER_MODE_1);
+ zassert_equal(rv, EC_ERROR_UNIMPLEMENTED, "Expected %d but got %d",
+ EC_ERROR_UNIMPLEMENTED, rv);
+
+ /* Part 3: attempt to set mode but cannot modify reg. */
+ i2c_common_emul_set_read_fail_reg(lis2dw12_emul_to_i2c_emul(emul),
+ LIS2DW12_ACC_MODE_ADDR);
+ rv = lis2dw12_set_power_mode(ms, LIS2DW12_LOW_POWER,
+ LIS2DW12_LOW_POWER_MODE_2);
+ zassert_equal(rv, EC_ERROR_INVAL, "Expected %d but got %d",
+ EC_ERROR_INVAL, rv);
+}
+
+static void test_lis2dw12_set_range(void)
+{
+ const struct emul *emul = emul_get_binding(EMUL_LABEL);
+ struct motion_sensor_t *ms = &motion_sensors[LIS2DW12_SENSOR_ID];
+ int rv;
+
+ /* Part 1: Happy path. Go above the max range; it will be automatically
+ * clamped.
+ */
+
+ rv = ms->drv->set_range(ms, LIS2DW12_ACCEL_FS_MAX_VAL + 1, 0);
+ zassert_equal(rv, EC_SUCCESS, "Expected %d but got %d", EC_SUCCESS, rv);
+ zassert_equal(ms->current_range, LIS2DW12_ACCEL_FS_MAX_VAL,
+ "Expected %d but got %d", LIS2DW12_ACCEL_FS_MAX_VAL,
+ ms->current_range);
+
+ /* Part 2: Error accessing register */
+ i2c_common_emul_set_read_fail_reg(lis2dw12_emul_to_i2c_emul(emul),
+ LIS2DW12_FS_ADDR);
+ rv = ms->drv->set_range(ms, LIS2DW12_ACCEL_FS_MAX_VAL, 0);
+ zassert_equal(rv, EC_ERROR_INVAL, "Expected %d but got %d",
+ EC_ERROR_INVAL, rv);
+}
+
+static void test_lis2dw12_set_rate(void)
+{
+ const struct emul *emul = emul_get_binding(EMUL_LABEL);
+ struct i2c_emul *i2c_emul = lis2dw12_emul_to_i2c_emul(emul);
+ struct motion_sensor_t *ms = &motion_sensors[LIS2DW12_SENSOR_ID];
+ struct stprivate_data *drv_data = ms->drv_data;
+ int rv;
+
+ /* Part 1: Turn off sensor with rate=0 */
+ rv = ms->drv->set_data_rate(ms, 0, 0);
+
+ zassert_equal(lis2dw12_emul_peek_odr(i2c_emul),
+ LIS2DW12_ODR_POWER_OFF_VAL,
+ "Output data rate should be %d but got %d",
+ LIS2DW12_ODR_POWER_OFF_VAL,
+ lis2dw12_emul_peek_odr(i2c_emul));
+ zassert_equal(drv_data->base.odr, LIS2DW12_ODR_POWER_OFF_VAL,
+ "Output data rate should be %d but got %d",
+ LIS2DW12_ODR_POWER_OFF_VAL, drv_data->base.odr);
+ zassert_equal(rv, EC_SUCCESS, "Returned %d but expected %d", rv,
+ EC_SUCCESS);
+
+ /* Part 2: Set some output data rates. We will request a certain rate
+ * and make sure the closest supported rate is used.
+ */
+
+ static const struct {
+ int requested_rate; /* millihertz */
+ enum lis2dw12_round_mode round;
+ int expected_norm_rate; /* millihertz */
+ uint8_t expected_reg_val;
+ } test_params[] = {
+ { 1000, ROUND_DOWN, LIS2DW12_ODR_MIN_VAL,
+ LIS2DW12_ODR_12HZ_VAL },
+ { 12501, ROUND_DOWN, 12500, LIS2DW12_ODR_12HZ_VAL },
+ { 25001, ROUND_DOWN, 25000, LIS2DW12_ODR_25HZ_VAL },
+ { 50001, ROUND_DOWN, 50000, LIS2DW12_ODR_50HZ_VAL },
+ { 100001, ROUND_DOWN, 100000, LIS2DW12_ODR_100HZ_VAL },
+ { 200001, ROUND_DOWN, 200000, LIS2DW12_ODR_200HZ_VAL },
+ { 400001, ROUND_DOWN, 400000, LIS2DW12_ODR_400HZ_VAL },
+ { 800001, ROUND_DOWN, 800000, LIS2DW12_ODR_800HZ_VAL },
+ { 1600001, ROUND_DOWN, 1600000, LIS2DW12_ODR_1_6kHZ_VAL },
+ { 3200001, ROUND_DOWN, LIS2DW12_ODR_MAX_VAL,
+ LIS2DW12_ODR_1_6kHZ_VAL },
+
+ { 1000, ROUND_UP, LIS2DW12_ODR_MIN_VAL, LIS2DW12_ODR_12HZ_VAL },
+ { 12501, ROUND_UP, 25000, LIS2DW12_ODR_25HZ_VAL },
+ { 25001, ROUND_UP, 50000, LIS2DW12_ODR_50HZ_VAL },
+ { 50001, ROUND_UP, 100000, LIS2DW12_ODR_100HZ_VAL },
+ { 100001, ROUND_UP, 200000, LIS2DW12_ODR_200HZ_VAL },
+ { 200001, ROUND_UP, 400000, LIS2DW12_ODR_400HZ_VAL },
+ { 400001, ROUND_UP, 800000, LIS2DW12_ODR_800HZ_VAL },
+ { 800001, ROUND_UP, 1600000, LIS2DW12_ODR_1_6kHZ_VAL },
+ { 1600001, ROUND_UP, LIS2DW12_ODR_MAX_VAL,
+ LIS2DW12_ODR_1_6kHZ_VAL },
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(test_params); i++) {
+ /* For each test vector in the above array */
+ drv_data->base.odr = -1;
+ rv = ms->drv->set_data_rate(ms, test_params[i].requested_rate,
+ test_params[i].round);
+
+ /* Check the normalized rate the driver chose */
+ zassert_equal(
+ drv_data->base.odr, test_params[i].expected_norm_rate,
+ "For requested rate %d, output data rate should be %d but got %d",
+ test_params[i].requested_rate,
+ test_params[i].expected_norm_rate, drv_data->base.odr);
+
+ /* Read ODR and mode bits back from CTRL1 register */
+ uint8_t odr_bits = lis2dw12_emul_peek_odr(i2c_emul);
+
+ zassert_equal(
+ odr_bits, test_params[i].expected_reg_val,
+ "For requested rate %d, ODR bits should be 0x%x but got 0x%x - %d",
+ test_params[i].requested_rate,
+ test_params[i].expected_reg_val, odr_bits,
+ LIS2DW12_ODR_MAX_VAL);
+
+ /* Check if high performance mode was enabled if rate >
+ * 200,000mHz
+ */
+
+ uint8_t mode_bits = lis2dw12_emul_peek_mode(i2c_emul);
+ uint8_t lpmode_bits = lis2dw12_emul_peek_lpmode(i2c_emul);
+
+ if (odr_bits > LIS2DW12_ODR_200HZ_VAL) {
+ /* High performance mode, LP mode immaterial */
+ zassert_equal(mode_bits, LIS2DW12_HIGH_PERF,
+ "MODE[1:0] should be 0x%x, but got 0x%x",
+ LIS2DW12_HIGH_PERF, mode_bits);
+
+ } else {
+ /* Low power mode, LP mode 2 */
+ zassert_equal(mode_bits, LIS2DW12_LOW_POWER,
+ "MODE[1:0] should be 0x%x, but got 0x%x",
+ LIS2DW12_LOW_POWER, mode_bits);
+
+ zassert_equal(
+ lpmode_bits, LIS2DW12_LOW_POWER_MODE_2,
+ "LPMODE[1:0] should be 0x%x, but got 0x%x",
+ LIS2DW12_LOW_POWER_MODE_2, lpmode_bits);
+ }
+ }
+}
+
+static void test_lis2dw12_read(void)
+{
+ const struct emul *emul = emul_get_binding(EMUL_LABEL);
+ struct i2c_emul *i2c_emul = lis2dw12_emul_to_i2c_emul(emul);
+ struct motion_sensor_t *ms = &motion_sensors[LIS2DW12_SENSOR_ID];
+ struct stprivate_data *drvdata = ms->drv_data;
+ intv3_t sample = { 0, 0, 0 };
+ int rv;
+
+ /* Reading requires a range to be set. Use 1 so it has no effect
+ * when scaling samples. Also need to set the sensor resolution
+ * manually.
+ */
+
+ ms->drv->set_range(ms, 1, 0);
+ drvdata->resol = LIS2DW12_RESOLUTION;
+
+ /* Part 1: Try to read from sensor, but cannot check status register for
+ * ready bit
+ */
+
+ i2c_common_emul_set_read_fail_reg(i2c_emul, LIS2DW12_STATUS_REG);
+
+ rv = ms->drv->read(ms, sample);
+
+ zassert_equal(rv, EC_ERROR_INVAL,
+ "Expected return val of %d but got %d", EC_ERROR_INVAL,
+ rv);
+
+ /* Part 2: Try to read sensor, but no new data is available. In this
+ * case, the driver should return the reading in from `ms->raw_xyz`
+ */
+
+ i2c_common_emul_set_read_fail_reg(i2c_emul,
+ I2C_COMMON_EMUL_NO_FAIL_REG);
+ lis2dw12_emul_clear_accel_reading(emul);
+ ms->raw_xyz[X] = 123;
+ ms->raw_xyz[Y] = 456;
+ ms->raw_xyz[Z] = 789;
+
+ rv = ms->drv->read(ms, sample);
+
+ zassert_equal(rv, EC_SUCCESS, "Expected return val of %d but got %d",
+ EC_SUCCESS, rv);
+ CHECK_XYZ_EQUALS(sample, ms->raw_xyz);
+
+ /* Part 3: Read from sensor w/ data ready, but an error occurs during
+ * read.
+ */
+ intv3_t fake_sample = { 100, 200, 300 };
+
+ i2c_common_emul_set_read_fail_reg(i2c_emul, LIS2DW12_OUT_X_L_ADDR);
+ lis2dw12_emul_set_accel_reading(emul, fake_sample);
+
+ rv = ms->drv->read(ms, sample);
+
+ zassert_equal(rv, EC_ERROR_INVAL,
+ "Expected return val of %d but got %d", EC_ERROR_INVAL,
+ rv);
+
+ /* Part 4: Success */
+
+ intv3_t expected_sample;
+
+ for (int i = 0; i < ARRAY_SIZE(expected_sample); i++) {
+ /* The read routine will normalize `fake_sample` to use the full
+ * range of INT16, so we need to compensate in our expected
+ * output
+ */
+
+ expected_sample[i] = fake_sample[i] *
+ (1 << (16 - LIS2DW12_RESOLUTION));
+ }
+
+ i2c_common_emul_set_read_fail_reg(i2c_emul,
+ I2C_COMMON_EMUL_NO_FAIL_REG);
+
+ lis2dw12_emul_set_accel_reading(emul, fake_sample);
+
+ rv = ms->drv->read(ms, sample);
+
+ zassert_equal(rv, EC_SUCCESS, "Expected return val of %d but got %d",
+ EC_SUCCESS, rv);
+ CHECK_XYZ_EQUALS(sample, expected_sample);
+}
+
void test_suite_lis2dw12(void)
{
ztest_test_suite(lis2dw12,
ztest_unit_test_setup_teardown(
test_lis2dw12_init__fail_read_who_am_i,
- lis2dw12_setup, unit_test_noop),
+ lis2dw12_setup, lis2dw12_setup),
ztest_unit_test_setup_teardown(
test_lis2dw12_init__fail_who_am_i,
- lis2dw12_setup, unit_test_noop),
+ lis2dw12_setup, lis2dw12_setup),
ztest_unit_test_setup_teardown(
test_lis2dw12_init__fail_write_soft_reset,
- lis2dw12_setup, unit_test_noop),
+ lis2dw12_setup, lis2dw12_setup),
ztest_unit_test_setup_teardown(
test_lis2dw12_init__timeout_read_soft_reset,
- lis2dw12_setup, unit_test_noop),
+ lis2dw12_setup, lis2dw12_setup),
ztest_unit_test_setup_teardown(
test_lis2dw12_init__fail_set_bdu,
- lis2dw12_setup, unit_test_noop));
+ lis2dw12_setup, lis2dw12_setup),
+ ztest_unit_test_setup_teardown(
+ test_lis2dw12_init__fail_set_lir,
+ lis2dw12_setup, lis2dw12_setup),
+ ztest_unit_test_setup_teardown(
+ test_lis2dw12_init__fail_set_power_mode,
+ lis2dw12_setup, lis2dw12_setup),
+ ztest_unit_test_setup_teardown(
+ test_lis2dw12_init__success,
+ lis2dw12_setup, lis2dw12_setup),
+ ztest_unit_test_setup_teardown(
+ test_lis2dw12_set_power_mode,
+ lis2dw12_setup, lis2dw12_setup),
+ ztest_unit_test_setup_teardown(
+ test_lis2dw12_set_range,
+ lis2dw12_setup, lis2dw12_setup),
+ ztest_unit_test_setup_teardown(
+ test_lis2dw12_set_rate,
+ lis2dw12_setup, lis2dw12_setup),
+ ztest_unit_test_setup_teardown(
+ test_lis2dw12_read,
+ lis2dw12_setup, lis2dw12_setup)
+ );
ztest_run_test_suite(lis2dw12);
}
diff --git a/zephyr/test/drivers/src/main.c b/zephyr/test/drivers/src/main.c
index 05fe12c8fc..687ea0785e 100644
--- a/zephyr/test/drivers/src/main.c
+++ b/zephyr/test/drivers/src/main.c
@@ -30,6 +30,8 @@ extern void test_suite_ppc_sn5s330(void);
extern void test_suite_cros_cbi(void);
extern void test_suite_tcpci(void);
extern void test_suite_ps8xxx(void);
+extern void test_suite_integration_usb(void);
+extern void test_suite_power_common(void);
void test_main(void)
{
@@ -61,4 +63,6 @@ void test_main(void)
test_suite_cros_cbi();
test_suite_tcpci();
test_suite_ps8xxx();
+ test_suite_integration_usb();
+ test_suite_power_common();
}
diff --git a/zephyr/test/drivers/src/power_common.c b/zephyr/test/drivers/src/power_common.c
new file mode 100644
index 0000000000..86e03ea38c
--- /dev/null
+++ b/zephyr/test/drivers/src/power_common.c
@@ -0,0 +1,677 @@
+/* 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 <ztest.h>
+#include <drivers/gpio.h>
+#include <drivers/gpio/gpio_emul.h>
+#include <shell/shell.h>
+#include <shell/shell_uart.h>
+
+#include "chipset.h"
+#include "common.h"
+#include "extpower.h"
+#include "hooks.h"
+#include "host_command.h"
+#include "power.h"
+#include "stubs.h"
+#include "task.h"
+
+#include "emul/emul_common_i2c.h"
+#include "emul/emul_smart_battery.h"
+
+#include "battery.h"
+#include "battery_smart.h"
+
+#define BATTERY_ORD DT_DEP_ORD(DT_NODELABEL(battery))
+
+#define GPIO_ACOK_OD_NODE DT_PATH(named_gpios, acok_od)
+#define GPIO_ACOK_OD_PIN DT_GPIO_PIN(GPIO_ACOK_OD_NODE, gpios)
+
+/* Description of all power states with chipset state masks */
+static struct {
+ /* Power state */
+ enum power_state p_state;
+ /*
+ * CHIPSET_STATE_* to which this state transition (the same as
+ * transition_from for static states)
+ */
+ int transition_to;
+ /* CHIPSET_STATE_* from which this state transition */
+ int transition_from;
+} test_power_state_desc[] = {
+ {
+ .p_state = POWER_G3,
+ .transition_to = CHIPSET_STATE_HARD_OFF,
+ .transition_from = CHIPSET_STATE_HARD_OFF,
+ },
+ {
+ .p_state = POWER_G3S5,
+ .transition_to = CHIPSET_STATE_SOFT_OFF,
+ .transition_from = CHIPSET_STATE_HARD_OFF,
+ },
+ {
+ .p_state = POWER_S5G3,
+ .transition_to = CHIPSET_STATE_HARD_OFF,
+ .transition_from = CHIPSET_STATE_SOFT_OFF,
+ },
+ {
+ .p_state = POWER_S5,
+ .transition_to = CHIPSET_STATE_SOFT_OFF,
+ .transition_from = CHIPSET_STATE_SOFT_OFF,
+ },
+ {
+ .p_state = POWER_S5S3,
+ .transition_to = CHIPSET_STATE_SUSPEND,
+ .transition_from = CHIPSET_STATE_SOFT_OFF,
+ },
+ {
+ .p_state = POWER_S3S5,
+ .transition_to = CHIPSET_STATE_SOFT_OFF,
+ .transition_from = CHIPSET_STATE_SUSPEND,
+ },
+ {
+ .p_state = POWER_S3,
+ .transition_to = CHIPSET_STATE_SUSPEND,
+ .transition_from = CHIPSET_STATE_SUSPEND,
+ },
+ {
+ .p_state = POWER_S3S0,
+ .transition_to = CHIPSET_STATE_ON,
+ .transition_from = CHIPSET_STATE_SUSPEND,
+ },
+ {
+ .p_state = POWER_S0S3,
+ .transition_to = CHIPSET_STATE_SUSPEND,
+ .transition_from = CHIPSET_STATE_ON,
+ },
+ {
+ .p_state = POWER_S0,
+ .transition_to = CHIPSET_STATE_ON,
+ .transition_from = CHIPSET_STATE_ON,
+ },
+};
+
+/*
+ * Chipset state masks used by chipset_in_state and
+ * chipset_in_or_transitioning_to_state tests
+ */
+static int in_state_test_masks[] = {
+ CHIPSET_STATE_HARD_OFF,
+ CHIPSET_STATE_SOFT_OFF,
+ CHIPSET_STATE_SUSPEND,
+ CHIPSET_STATE_ON,
+ CHIPSET_STATE_STANDBY,
+ CHIPSET_STATE_ANY_OFF,
+ CHIPSET_STATE_ANY_SUSPEND,
+ CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_SOFT_OFF,
+};
+
+/** Test chipset_in_state() for each state */
+static void test_power_chipset_in_state(void)
+{
+ bool expected_in_state;
+ bool transition_from;
+ bool transition_to;
+ bool in_state;
+ int mask;
+
+ for (int i = 0; i < ARRAY_SIZE(test_power_state_desc); i++) {
+ /* Set given power state */
+ power_set_state(test_power_state_desc[i].p_state);
+ /* Test with selected state masks */
+ for (int j = 0; j < ARRAY_SIZE(in_state_test_masks); j++) {
+ mask = in_state_test_masks[j];
+ /*
+ * Currently tested mask match with state if it match
+ * with transition_to and from chipset states
+ */
+ transition_to =
+ mask & test_power_state_desc[i].transition_to;
+ transition_from =
+ mask & test_power_state_desc[i].transition_from;
+ expected_in_state = transition_to && transition_from;
+ in_state = chipset_in_state(mask);
+ zassert_equal(expected_in_state, in_state,
+ "Wrong chipset_in_state() == %d, "
+ "should be %d; mask 0x%x; power state %d "
+ "in test case %d",
+ in_state, expected_in_state, mask,
+ test_power_state_desc[i].p_state, i);
+ }
+ }
+}
+
+/** Test chipset_in_or_transitioning_to_state() for each state */
+static void test_power_chipset_in_or_transitioning_to_state(void)
+{
+ bool expected_in_state;
+ bool in_state;
+ int mask;
+
+ for (int i = 0; i < ARRAY_SIZE(test_power_state_desc); i++) {
+ /* Set given power state */
+ power_set_state(test_power_state_desc[i].p_state);
+ /* Test with selected state masks */
+ for (int j = 0; j < ARRAY_SIZE(in_state_test_masks); j++) {
+ mask = in_state_test_masks[j];
+ /*
+ * Currently tested mask match with state if it match
+ * with transition_to chipset state
+ */
+ expected_in_state =
+ mask & test_power_state_desc[i].transition_to;
+ in_state = chipset_in_or_transitioning_to_state(mask);
+ zassert_equal(expected_in_state, in_state,
+ "Wrong "
+ "chipset_in_or_transitioning_to_state() "
+ "== %d, should be %d; mask 0x%x; "
+ "power state %d in test case %d",
+ in_state, expected_in_state, mask,
+ test_power_state_desc[i].p_state, i);
+ }
+ }
+}
+
+/** Test using chipset_exit_hard_off() in different power states */
+static void test_power_exit_hard_off(void)
+{
+ /* Force initial state */
+ force_power_state(true, POWER_G3);
+ zassert_equal(POWER_G3, power_get_state(), NULL);
+
+ /* Stop forcing state */
+ force_power_state(false, 0);
+
+ /* Test after exit hard off, we reach G3S5 */
+ chipset_exit_hard_off();
+ /*
+ * TODO(b/201420132) - chipset_exit_hard_off() is waking up
+ * TASK_ID_CHIPSET Sleep is required to run chipset task before
+ * continuing with test
+ */
+ k_msleep(1);
+ zassert_equal(POWER_G3S5, power_get_state(), NULL);
+
+ /* Go back to G3 and check we stay there */
+ force_power_state(true, POWER_G3);
+ force_power_state(false, 0);
+ zassert_equal(POWER_G3, power_get_state(), NULL);
+
+ /* Exit G3 again */
+ chipset_exit_hard_off();
+ /* TODO(b/201420132) - see comment above */
+ k_msleep(1);
+ zassert_equal(POWER_G3S5, power_get_state(), NULL);
+
+ /* Go to S5G3 */
+ force_power_state(true, POWER_S5G3);
+ zassert_equal(POWER_S5G3, power_get_state(), NULL);
+
+ /* Test exit hard off in S5G3 -- should immedietly exit G3 */
+ chipset_exit_hard_off();
+ /* Go back to G3 and check we exit it to G3S5 */
+ force_power_state(true, POWER_G3);
+ zassert_equal(POWER_G3S5, power_get_state(), NULL);
+
+ /* Test exit hard off is cleared on entering S5 */
+ chipset_exit_hard_off();
+ force_power_state(true, POWER_S5);
+ zassert_equal(POWER_S5, power_get_state(), NULL);
+ /* Go back to G3 and check we stay in G3 */
+ force_power_state(true, POWER_G3);
+ force_power_state(false, 0);
+ zassert_equal(POWER_G3, power_get_state(), NULL);
+
+ /* Test exit hard off doesn't work on other states */
+ force_power_state(true, POWER_S5S3);
+ force_power_state(false, 0);
+ zassert_equal(POWER_S5S3, power_get_state(), NULL);
+ chipset_exit_hard_off();
+ /* TODO(b/201420132) - see comment above */
+ k_msleep(1);
+
+ /* Go back to G3 and check we stay in G3 */
+ force_power_state(true, POWER_G3);
+ force_power_state(false, 0);
+ zassert_equal(POWER_G3, power_get_state(), NULL);
+}
+
+/* Test reboot ap on g3 host command is triggering reboot */
+static void test_power_reboot_ap_at_g3(void)
+{
+ struct ec_params_reboot_ap_on_g3_v1 params;
+ struct host_cmd_handler_args args = {
+ .command = EC_CMD_REBOOT_AP_ON_G3,
+ .version = 0,
+ .send_response = stub_send_response_callback,
+ .params = &params,
+ .params_size = sizeof(params),
+ };
+ int offset_for_still_in_g3_test;
+ int delay_ms;
+
+ /* Force initial state S0 */
+ force_power_state(true, POWER_S0);
+ zassert_equal(POWER_S0, power_get_state(), NULL);
+
+ /* Test version 0 (no delay argument) */
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+
+ /* Go to G3 and check if reboot is triggered */
+ force_power_state(true, POWER_G3);
+ zassert_equal(POWER_G3S5, power_get_state(), NULL);
+
+ /* Test version 1 (with delay argument) */
+ args.version = 1;
+ delay_ms = 3000;
+ params.reboot_ap_at_g3_delay = delay_ms / 1000; /* in seconds */
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+
+ /* Go to G3 and check if reboot is triggered after delay */
+ force_power_state(true, POWER_G3);
+ force_power_state(false, 0);
+ zassert_equal(POWER_G3, power_get_state(), NULL);
+ /*
+ * Arbitrary chosen offset before end of reboot delay to check if G3
+ * state wasn't left too soon
+ */
+ offset_for_still_in_g3_test = 50;
+ k_msleep(delay_ms - offset_for_still_in_g3_test);
+ /* Test if still in G3 */
+ zassert_equal(POWER_G3, power_get_state(), NULL);
+ /*
+ * power_common_state() use for loop with 100ms sleeps. msleep() wait at
+ * least specified time, so wait 10% longer than specified delay to take
+ * this into account.
+ */
+ k_msleep(offset_for_still_in_g3_test + delay_ms / 10);
+ /* Test if reboot is triggered */
+ zassert_equal(POWER_G3S5, power_get_state(), NULL);
+}
+
+/** Test setting cutoff and stay-up battery levels through host command */
+static void test_power_hc_smart_discharge(void)
+{
+ struct ec_response_smart_discharge response;
+ struct ec_params_smart_discharge params;
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND(EC_CMD_SMART_DISCHARGE, 0, response, params);
+ struct i2c_emul *emul;
+ int hours_to_zero;
+ int hibern_drate;
+ int cutoff_drate;
+ int stayup_cap;
+ int cutoff_cap;
+
+ emul = sbat_emul_get_ptr(BATTERY_ORD);
+
+ /* Set up host command parameters */
+ params.flags = EC_SMART_DISCHARGE_FLAGS_SET;
+
+ /* Test fail when battery capacity is not available */
+ i2c_common_emul_set_read_fail_reg(emul, SB_FULL_CHARGE_CAPACITY);
+ zassert_equal(EC_RES_UNAVAILABLE, host_command_process(&args), NULL);
+ i2c_common_emul_set_read_fail_reg(emul, I2C_COMMON_EMUL_NO_FAIL_REG);
+
+ /* Setup discharge rates */
+ params.drate.hibern = 10;
+ params.drate.cutoff = 100;
+ /* Test fail on higher discahrge in hibernation than cutoff */
+ zassert_equal(EC_RES_INVALID_PARAM, host_command_process(&args), NULL);
+
+ /* Setup discharge rates */
+ params.drate.hibern = 10;
+ params.drate.cutoff = 0;
+ /* Test fail on only one discharge rate set to 0 */
+ zassert_equal(EC_RES_INVALID_PARAM, host_command_process(&args), NULL);
+
+ /* Setup correct parameters */
+ hours_to_zero = 1000;
+ hibern_drate = 100; /* uA */
+ cutoff_drate = 10; /* uA */
+ /* Need at least 100 mA capacity to stay 1000h using 0.1mAh */
+ stayup_cap = hibern_drate * hours_to_zero / 1000;
+ /* Need at least 10 mA capacity to stay 1000h using 0.01mAh */
+ cutoff_cap = cutoff_drate * hours_to_zero / 1000;
+
+ params.drate.hibern = hibern_drate;
+ params.drate.cutoff = cutoff_drate;
+ params.hours_to_zero = hours_to_zero;
+
+ /* Test if correct values are set */
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+ zassert_equal(hibern_drate, response.drate.hibern, NULL);
+ zassert_equal(cutoff_drate, response.drate.cutoff, NULL);
+ zassert_equal(hours_to_zero, response.hours_to_zero, NULL);
+ zassert_equal(stayup_cap, response.dzone.stayup, NULL);
+ zassert_equal(cutoff_cap, response.dzone.cutoff, NULL);
+
+ /* Setup discharge rate to 0 */
+ params.drate.hibern = 0;
+ params.drate.cutoff = 0;
+ /* Update hours to zero */
+ hours_to_zero = 2000;
+ params.hours_to_zero = hours_to_zero;
+ /* Need at least 200 mA capacity to stay 2000h using 0.1mAh */
+ stayup_cap = hibern_drate * hours_to_zero / 1000;
+ /* Need at least 20 mA capacity to stay 2000h using 0.01mAh */
+ cutoff_cap = cutoff_drate * hours_to_zero / 1000;
+
+ /* Test that command doesn't change drate but apply new hours to zero */
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+ zassert_equal(hibern_drate, response.drate.hibern, NULL);
+ zassert_equal(cutoff_drate, response.drate.cutoff, NULL);
+ zassert_equal(hours_to_zero, response.hours_to_zero, NULL);
+ zassert_equal(stayup_cap, response.dzone.stayup, NULL);
+ zassert_equal(cutoff_cap, response.dzone.cutoff, NULL);
+
+ /* Setup any parameters != 0 */
+ params.drate.hibern = 1000;
+ params.drate.cutoff = 1000;
+ /* Clear set flag */
+ params.flags = 0;
+
+ /* Test that command doesn't change drate and dzone */
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+ zassert_equal(hibern_drate, response.drate.hibern, NULL);
+ zassert_equal(cutoff_drate, response.drate.cutoff, NULL);
+ zassert_equal(hours_to_zero, response.hours_to_zero, NULL);
+ zassert_equal(stayup_cap, response.dzone.stayup, NULL);
+ zassert_equal(cutoff_cap, response.dzone.cutoff, NULL);
+}
+
+/**
+ * Test if default board_system_is_idle() recognize cutoff and stay-up
+ * levels correctly.
+ */
+static void test_power_board_system_is_idle(void)
+{
+ struct ec_response_smart_discharge response;
+ struct ec_params_smart_discharge params;
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND(EC_CMD_SMART_DISCHARGE, 0, response, params);
+ struct sbat_emul_bat_data *bat;
+ struct i2c_emul *emul;
+ uint64_t last_shutdown_time = 0;
+ uint64_t target;
+ uint64_t now;
+
+ emul = sbat_emul_get_ptr(BATTERY_ORD);
+ bat = sbat_emul_get_bat_data(emul);
+
+ /* Set up host command parameters */
+ params.drate.hibern = 100; /* uA */
+ params.drate.cutoff = 10; /* uA */
+ params.hours_to_zero = 1000; /* h */
+ params.flags = EC_SMART_DISCHARGE_FLAGS_SET;
+ /* Set stay-up and cutoff zones */
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+
+ /* Test shutdown ignore is send when target time is in future */
+ target = 1125;
+ now = 1000;
+ zassert_equal(CRITICAL_SHUTDOWN_IGNORE,
+ board_system_is_idle(last_shutdown_time, &target, now),
+ NULL);
+
+ /* Set "now" time after target time */
+ now = target + 30;
+
+ /*
+ * Test hibernation is requested when battery remaining capacity
+ * is not available
+ */
+ i2c_common_emul_set_read_fail_reg(emul, SB_REMAINING_CAPACITY);
+ zassert_equal(CRITICAL_SHUTDOWN_HIBERNATE,
+ board_system_is_idle(last_shutdown_time, &target, now),
+ NULL);
+ i2c_common_emul_set_read_fail_reg(emul, I2C_COMMON_EMUL_NO_FAIL_REG);
+
+ /* Setup remaining capacity to trigger cutoff */
+ bat->cap = response.dzone.cutoff - 5;
+ zassert_equal(CRITICAL_SHUTDOWN_CUTOFF,
+ board_system_is_idle(last_shutdown_time, &target, now),
+ NULL);
+
+ /* Setup remaining capacity to trigger stay-up and ignore shutdown */
+ bat->cap = response.dzone.stayup - 5;
+ zassert_equal(CRITICAL_SHUTDOWN_IGNORE,
+ board_system_is_idle(last_shutdown_time, &target, now),
+ NULL);
+
+ /* Setup remaining capacity to be in safe zone to hibernate */
+ bat->cap = response.dzone.stayup + 5;
+ zassert_equal(CRITICAL_SHUTDOWN_HIBERNATE,
+ board_system_is_idle(last_shutdown_time, &target, now),
+ NULL);
+}
+
+/**
+ * Common setup for hibernation delay tests. Smart discharge zone is setup,
+ * battery is set in safe zone (which trigger hibernation), power state is
+ * set to G3 and AC is disabled. system_hibernate mock is reset.
+ */
+static void setup_hibernation_delay(void)
+{
+ struct ec_response_smart_discharge response;
+ struct ec_params_smart_discharge params;
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND(EC_CMD_SMART_DISCHARGE, 0, response, params);
+ const struct device *acok_dev =
+ DEVICE_DT_GET(DT_GPIO_CTLR(GPIO_ACOK_OD_NODE, gpios));
+ struct sbat_emul_bat_data *bat;
+ struct i2c_emul *emul;
+
+ emul = sbat_emul_get_ptr(BATTERY_ORD);
+ bat = sbat_emul_get_bat_data(emul);
+
+ /* Setup smart discharge zone and set capacity to safe zone */
+ params.drate.hibern = 100; /* uA */
+ params.drate.cutoff = 10; /* uA */
+ params.hours_to_zero = 10000; /* h */
+ params.flags = EC_SMART_DISCHARGE_FLAGS_SET;
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+ /*
+ * Make sure that battery is in safe zone in good condition to
+ * not trigger hibernate in charge_state_v2.c
+ */
+ bat->cap = response.dzone.stayup + 5;
+ bat->volt = battery_get_info()->voltage_normal;
+
+ /* Force initial state */
+ force_power_state(true, POWER_G3);
+ zassert_equal(POWER_G3, power_get_state(), NULL);
+
+ /* Stop forcing state */
+ force_power_state(false, 0);
+
+ /* Disable AC */
+ zassert_ok(gpio_emul_input_set(acok_dev, GPIO_ACOK_OD_PIN, 0), NULL);
+ msleep(CONFIG_EXTPOWER_DEBOUNCE_MS + 1);
+ zassert_equal(0, extpower_is_present(), NULL);
+
+ RESET_FAKE(system_hibernate);
+}
+
+/** Test setting hibernation delay through host command */
+static void test_power_hc_hibernation_delay(void)
+{
+ struct ec_response_hibernation_delay response;
+ struct ec_params_hibernation_delay params;
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND(EC_CMD_HIBERNATION_DELAY, 0, response,
+ params);
+ const struct device *acok_dev =
+ DEVICE_DT_GET(DT_GPIO_CTLR(GPIO_ACOK_OD_NODE, gpios));
+ uint32_t h_delay;
+ int sleep_time;
+
+ /* Set hibernate delay */
+ h_delay = 9;
+ params.seconds = h_delay;
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+
+ zassert_equal(0, response.time_g3, "Time from last G3 enter %d != 0",
+ response.time_g3);
+ zassert_equal(h_delay, response.time_remaining,
+ "Time to hibernation %d != %d",
+ response.time_remaining, h_delay);
+ zassert_equal(h_delay, response.hibernate_delay,
+ "Hibernation delay %d != %d",
+ h_delay, response.hibernate_delay);
+
+ /* Kick chipset task to process new hibernation delay */
+ task_wake(TASK_ID_CHIPSET);
+ /* Wait some arbitrary time less than hibernate delay */
+ sleep_time = 6;
+ k_msleep(sleep_time * 1000);
+
+ /* Get hibernate delay */
+ params.seconds = 0;
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+
+ zassert_equal(sleep_time, response.time_g3,
+ "Time from last G3 enter %d != %d",
+ response.time_g3, sleep_time);
+ zassert_equal(h_delay - sleep_time, response.time_remaining,
+ "Time to hibernation %d != %d",
+ response.time_remaining, h_delay - sleep_time);
+ zassert_equal(h_delay, response.hibernate_delay,
+ "Hibernation delay %d != %d",
+ h_delay, response.hibernate_delay);
+ zassert_equal(0, system_hibernate_fake.call_count,
+ "system_hibernate() shouldn't be called before delay");
+
+ /* Wait to end of the hibenate delay */
+ k_msleep((h_delay - sleep_time) * 1000);
+
+ /* Get hibernate delay */
+ params.seconds = 0;
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+
+ zassert_equal(h_delay, response.time_g3,
+ "Time from last G3 enter %d != %d",
+ response.time_g3, h_delay);
+ zassert_equal(0, response.time_remaining,
+ "Time to hibernation %d != 0",
+ response.time_remaining);
+ zassert_equal(h_delay, response.hibernate_delay,
+ "Hibernation delay %d != %d",
+ h_delay, response.hibernate_delay);
+ zassert_equal(1, system_hibernate_fake.call_count,
+ "system_hibernate() should be called after delay %d",
+ system_hibernate_fake.call_count);
+
+ /* Wait some more time */
+ k_msleep(2000);
+
+ /* Get hibernate delay */
+ params.seconds = 0;
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+
+ /* After hibernation, remaining time shouldn't be negative */
+ zassert_equal(0, response.time_remaining,
+ "Time to hibernation %d != 0",
+ response.time_remaining);
+
+ /* Enable AC */
+ zassert_ok(gpio_emul_input_set(acok_dev, GPIO_ACOK_OD_PIN, 1), NULL);
+ msleep(CONFIG_EXTPOWER_DEBOUNCE_MS + 1);
+ zassert_equal(1, extpower_is_present(), NULL);
+
+ /* Reset system_hibernate fake to check that it is not called on AC */
+ RESET_FAKE(system_hibernate);
+ /* Allow chipset task to spin with enabled AC */
+ task_wake(TASK_ID_CHIPSET);
+ k_msleep(1);
+
+ /* Get hibernate delay */
+ params.seconds = 0;
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+
+ zassert_equal(0, response.time_g3,
+ "Time from last G3 enter %d should be 0 on AC",
+ response.time_g3);
+ zassert_equal(0, system_hibernate_fake.call_count,
+ "system_hibernate() shouldn't be called on AC");
+
+ /* Disable AC */
+ zassert_ok(gpio_emul_input_set(acok_dev, GPIO_ACOK_OD_PIN, 0), NULL);
+ msleep(CONFIG_EXTPOWER_DEBOUNCE_MS + 1);
+ zassert_equal(0, extpower_is_present(), NULL);
+
+ /* Go to different state */
+ force_power_state(true, POWER_G3S5);
+ zassert_equal(POWER_G3S5, power_get_state(), NULL);
+
+ /* Stop forcing state */
+ force_power_state(false, 0);
+
+ /* Get hibernate delay */
+ params.seconds = 0;
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+
+ zassert_equal(0, response.time_g3,
+ "Time from last G3 enter %d should be 0 on state != G3",
+ response.time_g3);
+}
+
+/** Test setting hibernation delay through UART command */
+static void test_power_cmd_hibernation_delay(void)
+{
+ uint32_t h_delay;
+ int sleep_time;
+
+ /* Test success on call without argument */
+ zassert_equal(EC_SUCCESS,
+ shell_execute_cmd(shell_backend_uart_get_ptr(),
+ "hibdelay"), NULL);
+
+ /* Test error on hibernation delay argument that is not a number */
+ zassert_equal(EC_ERROR_PARAM1,
+ shell_execute_cmd(shell_backend_uart_get_ptr(),
+ "hibdelay test1"), NULL);
+
+ /* Set hibernate delay */
+ h_delay = 3;
+ zassert_equal(EC_SUCCESS,
+ shell_execute_cmd(shell_backend_uart_get_ptr(),
+ "hibdelay 3"), NULL);
+
+ /* Kick chipset task to process new hibernation delay */
+ task_wake(TASK_ID_CHIPSET);
+ /* Wait some arbitrary time less than hibernate delay */
+ sleep_time = 2;
+ k_msleep(sleep_time * 1000);
+
+ zassert_equal(0, system_hibernate_fake.call_count,
+ "system_hibernate() shouldn't be called before delay");
+
+ /* Wait to end of the hibenate delay */
+ k_msleep((h_delay - sleep_time) * 1000);
+
+ zassert_equal(1, system_hibernate_fake.call_count,
+ "system_hibernate() should be called after delay %d",
+ system_hibernate_fake.call_count);
+}
+
+void test_suite_power_common(void)
+{
+ ztest_test_suite(power_common,
+ ztest_unit_test(test_power_chipset_in_state),
+ ztest_unit_test(
+ test_power_chipset_in_or_transitioning_to_state),
+ ztest_unit_test(test_power_exit_hard_off),
+ ztest_unit_test(test_power_reboot_ap_at_g3),
+ ztest_unit_test(test_power_hc_smart_discharge),
+ ztest_unit_test(test_power_board_system_is_idle),
+ ztest_unit_test_setup_teardown(
+ test_power_hc_hibernation_delay,
+ setup_hibernation_delay, unit_test_noop),
+ ztest_unit_test_setup_teardown(
+ test_power_cmd_hibernation_delay,
+ setup_hibernation_delay, unit_test_noop));
+ ztest_run_test_suite(power_common);
+}
diff --git a/zephyr/test/drivers/src/ppc.c b/zephyr/test/drivers/src/ppc.c
index 740c7a0aea..5a729de3d6 100644
--- a/zephyr/test/drivers/src/ppc.c
+++ b/zephyr/test/drivers/src/ppc.c
@@ -23,6 +23,109 @@
static const int syv682x_port = 1;
+static void check_control_1_default_init(uint8_t control_1)
+{
+ /*
+ * During init, when not in dead battery mode, the driver should
+ * configure the high-voltage channel as sink but leave the power path
+ * disabled. The driver should set the current limits according to
+ * configuration.
+ */
+ int ilim;
+
+ zassert_true(control_1 & SYV682X_CONTROL_1_PWR_ENB,
+ "Default init, but power path enabled");
+ ilim = (control_1 & SYV682X_HV_ILIM_MASK) >> SYV682X_HV_ILIM_BIT_SHIFT;
+ zassert_equal(ilim, CONFIG_PLATFORM_EC_USBC_PPC_SYV682X_HV_ILIM,
+ "Default init, but HV current limit set to %d", ilim);
+ zassert_false(control_1 & SYV682X_CONTROL_1_HV_DR,
+ "Default init, but source mode selected");
+ zassert_true(control_1 & SYV682X_CONTROL_1_CH_SEL,
+ "Default init, but 5V power path selected");
+}
+
+static void test_ppc_syv682x_init(void)
+{
+ struct i2c_emul *emul = syv682x_emul_get(SYV682X_ORD);
+ const struct device *gpio_dev =
+ DEVICE_DT_GET(DT_GPIO_CTLR(GPIO_USB_C1_FRS_EN_PATH, gpios));
+ uint8_t reg;
+ int ilim;
+
+ /*
+ * With a dead battery, the device powers up sinking VBUS, and the
+ * driver should keep that going..
+ */
+ zassert_ok(syv682x_emul_set_reg(emul, SYV682X_CONTROL_1_REG,
+ SYV682X_CONTROL_1_CH_SEL), NULL);
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_VSAFE_5V,
+ SYV682X_CONTROL_4_NONE);
+ zassert_ok(ppc_init(syv682x_port), "PPC init failed");
+ zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_1_REG, &reg),
+ NULL);
+ zassert_true(reg & SYV682X_CONTROL_1_CH_SEL,
+ "Dead battery init, but CH_SEL set to 5V power path");
+ zassert_false(reg &
+ (SYV682X_CONTROL_1_PWR_ENB | SYV682X_CONTROL_1_HV_DR),
+ "Dead battery init, but CONTROL_1 is 0x%x", reg);
+ zassert_false(ppc_is_sourcing_vbus(syv682x_port),
+ "Dead battery init, but VBUS source enabled");
+
+ /* With VBUS at vSafe0V, init should set the default configuration. */
+ zassert_ok(syv682x_emul_set_reg(emul, SYV682X_CONTROL_1_REG,
+ SYV682X_CONTROL_1_PWR_ENB), NULL);
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_VSAFE_0V,
+ SYV682X_CONTROL_4_NONE);
+ zassert_ok(ppc_init(syv682x_port), "PPC init failed");
+ zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_1_REG, &reg),
+ NULL);
+ check_control_1_default_init(reg);
+
+ /* With sink disabled, init should do the same thing. */
+ zassert_ok(syv682x_emul_set_reg(emul, SYV682X_CONTROL_1_REG,
+ SYV682X_CONTROL_1_CH_SEL), NULL);
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_VSAFE_0V,
+ SYV682X_CONTROL_4_NONE);
+ zassert_ok(ppc_init(syv682x_port), "PPC init failed");
+ zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_1_REG, &reg),
+ NULL);
+ check_control_1_default_init(reg);
+
+ /*
+ * Any init sequence should also disable the FRS GPIO, set the 5V
+ * current limit according to configuration, set over-current, over-
+ * voltage, and discharge parameters appropriately, and enable CC lines.
+ */
+ zassert_equal(gpio_emul_output_get(gpio_dev, GPIO_USB_C1_FRS_EN_PORT),
+ 0, "FRS enabled, but FRS GPIO not asserted");
+ ilim = (reg & SYV682X_5V_ILIM_MASK) >> SYV682X_5V_ILIM_BIT_SHIFT;
+ zassert_equal(ilim, CONFIG_PLATFORM_EC_USB_PD_PULLUP,
+ "Default init, but 5V current limit set to %d", ilim);
+ zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_2_REG, &reg),
+ NULL);
+ zassert_equal(reg, (SYV682X_OC_DELAY_10MS << SYV682X_OC_DELAY_SHIFT) |
+ (SYV682X_DSG_RON_200_OHM << SYV682X_DSG_RON_SHIFT) |
+ (SYV682X_DSG_TIME_50MS << SYV682X_DSG_TIME_SHIFT),
+ "Default init, but CONTROL_2 is 0x%x", reg);
+ zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_3_REG, &reg),
+ NULL);
+ zassert_equal(reg, (SYV682X_OVP_23_7 << SYV682X_OVP_BIT_SHIFT) |
+ SYV682X_RVS_MASK,
+ "Default init, but CONTROL_3 is 0x%x", reg);
+ zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_4_REG, &reg),
+ NULL);
+ zassert_equal(reg & ~SYV682X_CONTROL_4_INT_MASK,
+ SYV682X_CONTROL_4_CC1_BPS | SYV682X_CONTROL_4_CC2_BPS,
+ "Default init, but CONTROL_4 is 0x%x", reg);
+
+ /* Disable the power path again. */
+ zassert_ok(syv682x_emul_set_reg(emul, SYV682X_CONTROL_1_REG,
+ SYV682X_CONTROL_1_PWR_ENB), NULL);
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_NONE,
+ SYV682X_CONTROL_4_NONE);
+
+}
+
static void test_ppc_syv682x_vbus_enable(void)
{
struct i2c_emul *emul = syv682x_emul_get(SYV682X_ORD);
@@ -51,21 +154,18 @@ static void test_ppc_syv682x_interrupt(void)
uint8_t reg;
/* An OC event less than 100 ms should not cause VBUS to turn off. */
- syv682x_emul_set_status(emul, SYV682X_STATUS_OC_5V);
- syv682x_interrupt(syv682x_port);
- /* TODO(b/201420132): Simulate passage of time instead of sleeping. */
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_OC_5V,
+ SYV682X_CONTROL_4_NONE);
msleep(50);
- syv682x_interrupt(syv682x_port);
zassert_true(ppc_is_sourcing_vbus(syv682x_port),
"PPC is not sourcing VBUS after 50 ms OC");
/* But one greater than 100 ms should. */
- /* TODO(b/201420132): Simulate passage of time instead of sleeping. */
msleep(60);
- syv682x_interrupt(syv682x_port);
zassert_false(ppc_is_sourcing_vbus(syv682x_port),
"PPC is sourcing VBUS after 100 ms OC");
- syv682x_emul_set_status(emul, 0x0);
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_NONE,
+ SYV682X_CONTROL_4_NONE);
/*
* TODO(b/190519131): Organize the tests to be more hermetic and avoid
* the following issue: The driver triggers overcurrent protection. If
@@ -81,24 +181,24 @@ static void test_ppc_syv682x_interrupt(void)
*/
zassert_ok(ppc_vbus_source_enable(syv682x_port, true),
"Source enable failed");
- syv682x_emul_set_status(emul, SYV682X_STATUS_TSD);
- syv682x_interrupt(syv682x_port);
- /* TODO(b/201420132): Simulate passage of time instead of sleeping. */
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_TSD,
+ SYV682X_CONTROL_4_NONE);
msleep(1);
zassert_false(ppc_is_sourcing_vbus(syv682x_port),
"PPC is sourcing power after TSD");
- syv682x_emul_set_status(emul, 0);
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_NONE,
+ SYV682X_CONTROL_4_NONE);
/* An OVP event should cause the driver to disable the source path. */
zassert_ok(ppc_vbus_source_enable(syv682x_port, true),
"Source enable failed");
- syv682x_emul_set_status(emul, SYV682X_STATUS_OVP);
- syv682x_interrupt(syv682x_port);
- /* TODO(b/201420132): Simulate passage of time instead of sleeping. */
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_OVP,
+ SYV682X_CONTROL_4_NONE);
msleep(1);
zassert_false(ppc_is_sourcing_vbus(syv682x_port),
"PPC is sourcing power after OVP");
- syv682x_emul_set_status(emul, 0);
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_NONE,
+ SYV682X_CONTROL_4_NONE);
/*
* A high-voltage OC while sinking should cause the driver to try to
@@ -107,52 +207,45 @@ static void test_ppc_syv682x_interrupt(void)
*/
zassert_ok(ppc_vbus_sink_enable(syv682x_port, true),
"Sink enable failed");
- syv682x_emul_set_status(emul, SYV682X_STATUS_OC_HV);
- syv682x_interrupt(syv682x_port);
- /* TODO(b/201420132): Simulate passage of time instead of sleeping. */
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_OC_HV,
+ SYV682X_CONTROL_4_NONE);
msleep(1);
zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_1_REG, &reg),
"Reading CONTROL_1 failed");
zassert_equal(reg & SYV682X_CONTROL_1_PWR_ENB, 0,
"Power path disabled after HV_OC handled");
- syv682x_emul_set_status(emul, SYV682X_STATUS_OC_HV);
- syv682x_interrupt(syv682x_port);
- /* TODO(b/201420132): Simulate passage of time instead of sleeping. */
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_OC_HV,
+ SYV682X_CONTROL_4_NONE);
msleep(1);
zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_1_REG, &reg),
"Reading CONTROL_1 failed");
zassert_equal(reg & SYV682X_CONTROL_1_PWR_ENB, 0,
"Power path disabled after HV_OC handled");
- syv682x_emul_set_status(emul, SYV682X_STATUS_OC_HV);
- syv682x_interrupt(syv682x_port);
- /* TODO(b/201420132): Simulate passage of time instead of sleeping. */
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_OC_HV,
+ SYV682X_CONTROL_4_NONE);
msleep(1);
zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_1_REG, &reg),
"Reading CONTROL_1 failed");
zassert_equal(reg & SYV682X_CONTROL_1_PWR_ENB,
SYV682X_CONTROL_1_PWR_ENB,
"Power path enabled after HV_OC handled 3 times");
- syv682x_emul_set_status(emul, 0);
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_NONE,
+ SYV682X_CONTROL_4_NONE);
/*
* A VCONN OC event less than 100 ms should not cause the driver to turn
* VCONN off.
*/
ppc_set_vconn(syv682x_port, true);
- syv682x_emul_set_control_4(emul, SYV682X_CONTROL_4_VCONN_OCP);
- syv682x_interrupt(syv682x_port);
- /* TODO(b/201420132): Simulate passage of time instead of sleeping. */
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_NONE,
+ SYV682X_CONTROL_4_VCONN_OCP);
msleep(1);
zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_4_REG, &reg),
"Reading CONTROL_4 failed");
zassert_true(reg &
(SYV682X_CONTROL_4_VCONN1 | SYV682X_CONTROL_4_VCONN2),
"VCONN disabled after initial VCONN OC");
- /* TODO(b/201420132): Simulate passage of time instead of sleeping. */
msleep(50);
- syv682x_interrupt(syv682x_port);
- /* TODO(b/201420132): Simulate passage of time instead of sleeping. */
- msleep(1);
zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_4_REG, &reg),
"Reading CONTROL_4 failed");
zassert_true(reg &
@@ -162,17 +255,14 @@ static void test_ppc_syv682x_interrupt(void)
* But if the event keeps going for over 100 ms continuously, the driver
* should turn VCONN off.
*/
- /* TODO(b/201420132): Simulate passage of time instead of sleeping. */
msleep(60);
- syv682x_interrupt(syv682x_port);
- /* TODO(b/201420132): Simulate passage of time instead of sleeping. */
- msleep(1);
zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_4_REG, &reg),
"Reading CONTROL_4 failed");
zassert_false(reg &
(SYV682X_CONTROL_4_VCONN1 | SYV682X_CONTROL_4_VCONN2),
"VCONN enabled after long VCONN OC");
- syv682x_emul_set_control_4(emul, 0);
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_NONE,
+ SYV682X_CONTROL_4_NONE);
/*
* A VCONN over-voltage (VBAT_OVP) event will cause the device to
@@ -181,9 +271,8 @@ static void test_ppc_syv682x_interrupt(void)
* driver should then run generic CC over-voltage handling.
*/
ppc_set_vconn(syv682x_port, true);
- syv682x_emul_set_control_4(emul, SYV682X_CONTROL_4_VBAT_OVP);
- syv682x_interrupt(syv682x_port);
- /* TODO(b/201420132): Simulate passage of time instead of sleeping. */
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_NONE,
+ SYV682X_CONTROL_4_VBAT_OVP);
msleep(1);
zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_4_REG, &reg),
"Reading CONTROL_4 failed");
@@ -199,7 +288,8 @@ static void test_ppc_syv682x_interrupt(void)
* to a CC over-voltage event. There is currently no easy way to test
* that a Hard Reset occurred.
*/
- syv682x_emul_set_control_4(emul, 0);
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_NONE,
+ SYV682X_CONTROL_4_NONE);
}
static void test_ppc_syv682x_frs(void)
@@ -252,23 +342,167 @@ static void test_ppc_syv682x_frs(void)
* An FRS event when the PPC is Sink should cause the PPC to switch from
* Sink to Source.
*/
- syv682x_emul_set_status(emul, SYV682X_STATUS_FRS);
- syv682x_interrupt(syv682x_port);
- /* TODO(b/201420132): Simulate passage of time instead of sleeping. */
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_FRS,
+ SYV682X_CONTROL_4_NONE);
msleep(1);
zassert_true(ppc_is_sourcing_vbus(syv682x_port),
"PPC is not sourcing VBUS after FRS signal handled");
- syv682x_emul_set_status(emul, 0);
+ syv682x_emul_set_condition(emul, SYV682X_STATUS_NONE,
+ SYV682X_CONTROL_4_NONE);
+}
+
+static void test_ppc_syv682x_source_current_limit(void)
+{
+ struct i2c_emul *emul = syv682x_emul_get(SYV682X_ORD);
+ uint8_t reg;
+ int ilim_val;
+
+ zassert_ok(ppc_set_vbus_source_current_limit(syv682x_port,
+ TYPEC_RP_USB),
+ "Could not set source current limit");
+ zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_1_REG, &reg),
+ "Reading CONTROL_1 failed");
+ ilim_val = (reg & SYV682X_5V_ILIM_MASK) >> SYV682X_5V_ILIM_BIT_SHIFT;
+ zassert_equal(reg & SYV682X_5V_ILIM_MASK, SYV682X_5V_ILIM_1_25,
+ "Set USB Rp value, but 5V_ILIM is %d", ilim_val);
+
+ zassert_ok(ppc_set_vbus_source_current_limit(syv682x_port,
+ TYPEC_RP_1A5),
+ "Could not set source current limit");
+ zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_1_REG, &reg),
+ "Reading CONTROL_1 failed");
+ ilim_val = (reg & SYV682X_5V_ILIM_MASK) >> SYV682X_5V_ILIM_BIT_SHIFT;
+ zassert_equal(ilim_val, SYV682X_5V_ILIM_1_75,
+ "Set 1.5A Rp value, but 5V_ILIM is %d", ilim_val);
+ zassert_ok(ppc_set_vbus_source_current_limit(syv682x_port,
+ TYPEC_RP_3A0),
+ "Could not set source current limit");
+ zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_1_REG, &reg),
+ "Reading CONTROL_1 failed");
+ ilim_val = (reg & SYV682X_5V_ILIM_MASK) >> SYV682X_5V_ILIM_BIT_SHIFT;
+ zassert_equal(ilim_val, SYV682X_5V_ILIM_3_30,
+ "Set 3.0A Rp value, but 5V_ILIM is %d", ilim_val);
}
-static void test_ppc_syv682x(void)
+static void test_ppc_syv682x_write_busy(void)
{
- zassert_ok(ppc_init(syv682x_port), "PPC init failed");
+ struct i2c_emul *emul = syv682x_emul_get(SYV682X_ORD);
+
+ /*
+ * Writes should fail while the BUSY bit is set, except that writes to
+ * CONTROL_4 should succeed on the SYV682C. 100 reads is intentionally
+ * many more than the driver is expected to make before reaching its
+ * timeout. It is not a goal of this test to verify the frequency of
+ * polling or the exact value of the timeout.
+ */
+ syv682x_emul_set_busy_reads(emul, 100);
+ zassert_equal(ppc_set_vbus_source_current_limit(syv682x_port,
+ TYPEC_RP_USB),
+ EC_ERROR_TIMEOUT, "SYV682 busy, but write completed");
+ zassert_ok(ppc_set_frs_enable(syv682x_port, false),
+ "Could not set CONTROL_4 while busy on SYV682C");
+
+ /*
+ * If the busy bit clears before the driver reaches its timeout, the
+ * write should succeed.
+ */
+ syv682x_emul_set_busy_reads(emul, 1);
+ zassert_equal(ppc_set_vbus_source_current_limit(syv682x_port,
+ TYPEC_RP_USB), 0,
+ "SYV682 not busy, but write failed");
+
+ syv682x_emul_set_busy_reads(emul, 0);
+}
+
+static void test_ppc_syv682x_dev_is_connected(void)
+{
+ struct i2c_emul *emul = syv682x_emul_get(SYV682X_ORD);
+ uint8_t reg;
+
+ zassert_ok(ppc_dev_is_connected(syv682x_port, PPC_DEV_SRC),
+ "Could not connect device as source");
+ zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_2_REG, &reg),
+ "Reading CONTROL_2 failed");
+ zassert_false(reg & SYV682X_CONTROL_2_FDSG,
+ "Connected as source, but force discharge enabled");
+
+ zassert_ok(ppc_dev_is_connected(syv682x_port, PPC_DEV_DISCONNECTED),
+ "Could not disconnect device");
+ zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_2_REG, &reg),
+ "Reading CONTROL_2 failed");
+ zassert_true(reg & SYV682X_CONTROL_2_FDSG,
+ "Disconnected, but force discharge disabled");
+
+ zassert_ok(ppc_dev_is_connected(syv682x_port, PPC_DEV_SNK),
+ "Could not connect device as source");
+}
+
+static void test_ppc_syv682x_vbus_sink_enable(void)
+{
+ struct i2c_emul *emul = syv682x_emul_get(SYV682X_ORD);
+ uint8_t reg;
+ int ilim;
+
+ /*
+ * If VBUS source is already enabled, disabling VBUS sink should
+ * trivially succeed.
+ */
+ zassert_ok(ppc_vbus_source_enable(syv682x_port, true),
+ "VBUS enable failed");
+ zassert_ok(ppc_vbus_sink_enable(syv682x_port, false),
+ "Sink disable failed");
+
+ /*
+ * After enabling VBUS sink, the HV power path should be enabled in sink
+ * mode with the configured current limit.
+ */
+ zassert_ok(ppc_vbus_source_enable(syv682x_port, false),
+ "VBUS enable failed");
+ zassert_ok(ppc_vbus_sink_enable(syv682x_port, true),
+ "Sink disable failed");
+ zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_1_REG, &reg),
+ NULL);
+ zassert_true(reg & SYV682X_CONTROL_1_CH_SEL,
+ "Sink enabled, but CH_SEL set to 5V power path");
+ zassert_false(reg & SYV682X_CONTROL_1_PWR_ENB,
+ "Sink enabled, but power path disabled");
+ zassert_false(reg & SYV682X_CONTROL_1_HV_DR,
+ "Sink enabled, but high-voltage path in source mode");
+ ilim = (reg & SYV682X_HV_ILIM_MASK) >> SYV682X_HV_ILIM_BIT_SHIFT;
+ zassert_equal(ilim, CONFIG_PLATFORM_EC_USBC_PPC_SYV682X_HV_ILIM,
+ "Sink enabled, but HV current limit set to %d", ilim);
+ zassert_ok(ppc_vbus_sink_enable(syv682x_port, false),
+ "Sink disable failed");
+ zassert_ok(syv682x_emul_get_reg(emul, SYV682X_CONTROL_1_REG, &reg),
+ NULL);
+ zassert_true(reg & SYV682X_CONTROL_1_PWR_ENB,
+ "Sink disabled, but power path enabled");
+}
+
+static void test_ppc_syv682x_ppc_dump(void)
+{
+ /*
+ * The ppc_dump command should succeed for this port. Don't check the
+ * output, since there are no standard requirements for that.
+ */
+ const struct ppc_drv *drv = ppc_chips[syv682x_port].drv;
+
+ zassert_ok(drv->reg_dump(syv682x_port), "ppc_dump command failed");
+}
+
+static void test_ppc_syv682x(void)
+{
+ test_ppc_syv682x_init();
test_ppc_syv682x_vbus_enable();
test_ppc_syv682x_interrupt();
test_ppc_syv682x_frs();
+ test_ppc_syv682x_source_current_limit();
+ test_ppc_syv682x_write_busy();
+ test_ppc_syv682x_dev_is_connected();
+ test_ppc_syv682x_vbus_sink_enable();
+ test_ppc_syv682x_ppc_dump();
}
void test_suite_ppc(void)
diff --git a/zephyr/test/drivers/src/ppc_sn5s330.c b/zephyr/test/drivers/src/ppc_sn5s330.c
index 95556e28cf..429b9b8c26 100644
--- a/zephyr/test/drivers/src/ppc_sn5s330.c
+++ b/zephyr/test/drivers/src/ppc_sn5s330.c
@@ -3,10 +3,12 @@
* found in the LICENSE file.
*/
+#include <kernel.h>
#include <device.h>
#include <devicetree.h>
#include <emul.h>
#include <ztest.h>
+#include <fff.h>
#include "driver/ppc/sn5s330.h"
#include "driver/ppc/sn5s330_public.h"
@@ -17,12 +19,49 @@
/** This must match the index of the sn5s330 in ppc_chips[] */
#define SN5S330_PORT 0
#define EMUL emul_get_binding(DT_LABEL(DT_NODELABEL(sn5s330_emul)))
+#define FUNC_SET1_ILIMPP1_MSK 0x1F
+#define SN5S330_INTERRUPT_DELAYMS 15
+
+FAKE_VOID_FUNC(sn5s330_emul_interrupt_set_stub);
/*
* TODO(b/203364783): Exclude other threads from interacting with the emulator
* to avoid test flakiness
*/
+struct intercept_write_data {
+ int reg_to_intercept;
+ uint8_t val_intercepted;
+};
+
+struct intercept_read_data {
+ int reg_to_intercept;
+ bool replace_reg_val;
+ uint8_t replacement_val;
+};
+
+static int intercept_read_func(struct i2c_emul *emul, int reg, uint8_t *val,
+ int bytes, void *data)
+{
+ struct intercept_read_data *test_data = data;
+
+ if (test_data->reg_to_intercept && test_data->replace_reg_val)
+ *val = test_data->replacement_val;
+
+ return EC_SUCCESS;
+}
+
+static int intercept_write_func(struct i2c_emul *emul, int reg, uint8_t val,
+ int bytes, void *data)
+{
+ struct intercept_write_data *test_data = data;
+
+ if (test_data->reg_to_intercept == reg)
+ test_data->val_intercepted = val;
+
+ return 1;
+}
+
static int fail_until_write_func(struct i2c_emul *emul, int reg, uint8_t val,
int bytes, void *data)
{
@@ -40,29 +79,300 @@ static void test_fail_once_func_set1(void)
const struct emul *emul = EMUL;
struct i2c_emul *i2c_emul = sn5s330_emul_to_i2c_emul(emul);
uint32_t count = 1;
- uint32_t func_set1_value;
+ uint8_t func_set1_value;
i2c_common_emul_set_write_func(i2c_emul, fail_until_write_func, &count);
zassert_ok(sn5s330_drv.init(SN5S330_PORT), NULL);
zassert_equal(count, 0, NULL);
- zassert_ok(sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET1,
- &func_set1_value),
- NULL);
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET1, &func_set1_value);
zassert_true((func_set1_value & SN5S330_ILIM_1_62) != 0, NULL);
i2c_common_emul_set_write_func(i2c_emul, NULL, NULL);
}
+static void test_dead_battery_boot_force_pp2_fets_set(void)
+{
+ const struct emul *emul = EMUL;
+ struct i2c_emul *i2c_emul = sn5s330_emul_to_i2c_emul(emul);
+ struct intercept_write_data test_write_data = {
+ .reg_to_intercept = SN5S330_FUNC_SET3,
+ .val_intercepted = 0,
+ };
+ struct intercept_read_data test_read_data = {
+ .reg_to_intercept = SN5S330_INT_STATUS_REG4,
+ .replace_reg_val = true,
+ .replacement_val = SN5S330_DB_BOOT,
+ };
+
+ i2c_common_emul_set_write_func(i2c_emul, intercept_write_func,
+ &test_write_data);
+ i2c_common_emul_set_read_func(i2c_emul, intercept_read_func,
+ &test_read_data);
+
+ zassert_ok(sn5s330_drv.init(SN5S330_PORT), NULL);
+
+ /*
+ * Although the device enables PP2_FET on dead battery boot by setting
+ * the PP2_EN bit, the driver also force sets this bit during dead
+ * battery boot by writing that bit to the FUNC_SET3 reg.
+ *
+ * TODO(b/207034759): Verify need or remove redundant PP2 set.
+ */
+ zassert_true(test_write_data.val_intercepted & SN5S330_PP2_EN, NULL);
+ zassert_false(sn5s330_drv.is_sourcing_vbus(SN5S330_PORT), NULL);
+}
+
+static void test_enter_low_power_mode(void)
+{
+ const struct emul *emul = EMUL;
+
+ uint8_t func_set2_reg;
+ uint8_t func_set3_reg;
+ uint8_t func_set4_reg;
+ uint8_t func_set9_reg;
+
+ /*
+ * Requirements were extracted from TI's recommended changes for octopus
+ * to lower power use during hibernate as well as the follow up changes
+ * we made to allow the device to wake up from hibernate.
+ *
+ * For Reference: b/111006203#comment35
+ */
+
+ zassert_ok(sn5s330_drv.init(SN5S330_PORT), NULL);
+ zassert_ok(sn5s330_drv.enter_low_power_mode(SN5S330_PORT), NULL);
+
+ /* 1) Verify VBUS power paths are off */
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET3, &func_set3_reg);
+ zassert_equal(func_set3_reg & SN5S330_PP1_EN, 0, NULL);
+ zassert_equal(func_set3_reg & SN5S330_PP2_EN, 0, NULL);
+
+ /* 2) Verify VCONN power path is off */
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET4, &func_set4_reg);
+ zassert_not_equal(func_set4_reg & SN5S330_CC_EN, 0, NULL);
+ zassert_equal(func_set4_reg & SN5S330_VCONN_EN, 0, NULL);
+
+ /* 3) Verify SBU FET is off */
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET2, &func_set2_reg);
+ zassert_equal(func_set2_reg & SN5S330_SBU_EN, 0, NULL);
+
+ /* 4) Verify VBUS and SBU OVP comparators are off */
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET9, &func_set9_reg);
+ zassert_equal(func_set9_reg & SN5S330_FORCE_OVP_EN_SBU, 0, NULL);
+ zassert_equal(func_set9_reg & SN5S330_PWR_OVR_VBUS, 0, NULL);
+ zassert_not_equal(func_set9_reg & SN5S330_OVP_EN_CC, 0, NULL);
+ zassert_equal(func_set9_reg & SN5S330_FORCE_ON_VBUS_OVP, 0, NULL);
+ zassert_equal(func_set9_reg & SN5S330_FORCE_ON_VBUS_UVP, 0, NULL);
+}
+
+static void test_vbus_source_sink_enable(void)
+{
+ const struct emul *emul = EMUL;
+ uint8_t func_set3_reg;
+
+ zassert_ok(sn5s330_drv.init(SN5S330_PORT), NULL);
+
+ /* Test enable/disable VBUS source FET */
+ zassert_ok(sn5s330_drv.vbus_source_enable(SN5S330_PORT, true), NULL);
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET3, &func_set3_reg);
+ zassert_not_equal(func_set3_reg & SN5S330_PP1_EN, 0, NULL);
+
+ zassert_ok(sn5s330_drv.vbus_source_enable(SN5S330_PORT, false), NULL);
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET3, &func_set3_reg);
+ zassert_equal(func_set3_reg & SN5S330_PP1_EN, 0, NULL);
+
+ /* Test enable/disable VBUS sink FET */
+ zassert_ok(sn5s330_drv.vbus_sink_enable(SN5S330_PORT, true), NULL);
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET3, &func_set3_reg);
+ zassert_not_equal(func_set3_reg & SN5S330_PP2_EN, 0, NULL);
+
+ zassert_ok(sn5s330_drv.vbus_sink_enable(SN5S330_PORT, false), NULL);
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET3, &func_set3_reg);
+ zassert_equal(func_set3_reg & SN5S330_PP2_EN, 0, NULL);
+}
+
+static void test_vbus_discharge(void)
+{
+ const struct emul *emul = EMUL;
+ uint8_t func_set3_reg;
+
+ zassert_ok(sn5s330_drv.init(SN5S330_PORT), NULL);
+
+ /* Test enable/disable VBUS discharging */
+ zassert_ok(sn5s330_drv.discharge_vbus(SN5S330_PORT, true), NULL);
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET3, &func_set3_reg);
+ zassert_not_equal(func_set3_reg & SN5S330_VBUS_DISCH_EN, 0, NULL);
+
+ zassert_ok(sn5s330_drv.discharge_vbus(SN5S330_PORT, false), NULL);
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET3, &func_set3_reg);
+ zassert_equal(func_set3_reg & SN5S330_VBUS_DISCH_EN, 0, NULL);
+}
+
+static void test_set_vbus_source_current_limit(void)
+{
+ const struct emul *emul = EMUL;
+ uint8_t func_set1_reg;
+
+ /* Test every TCPC Pull Resistance Value */
+ zassert_ok(sn5s330_drv.init(SN5S330_PORT), NULL);
+
+ /* USB */
+ zassert_ok(sn5s330_drv.set_vbus_source_current_limit(SN5S330_PORT,
+ TYPEC_RP_USB),
+ NULL);
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET1, &func_set1_reg);
+ zassert_equal(func_set1_reg & FUNC_SET1_ILIMPP1_MSK, SN5S330_ILIM_0_63,
+ NULL);
+
+ /* 1.5A */
+ zassert_ok(sn5s330_drv.set_vbus_source_current_limit(SN5S330_PORT,
+ TYPEC_RP_1A5),
+ NULL);
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET1, &func_set1_reg);
+ zassert_equal(func_set1_reg & FUNC_SET1_ILIMPP1_MSK, SN5S330_ILIM_1_62,
+ NULL);
+
+ /* 3.0A */
+ zassert_ok(sn5s330_drv.set_vbus_source_current_limit(SN5S330_PORT,
+ TYPEC_RP_3A0),
+ NULL);
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET1, &func_set1_reg);
+ zassert_equal(func_set1_reg & FUNC_SET1_ILIMPP1_MSK, SN5S330_ILIM_3_06,
+ NULL);
+
+ /* Unknown/Reserved - We set result as USB */
+ zassert_ok(sn5s330_drv.set_vbus_source_current_limit(SN5S330_PORT,
+ TYPEC_RP_RESERVED),
+ NULL);
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET1, &func_set1_reg);
+ zassert_equal(func_set1_reg & FUNC_SET1_ILIMPP1_MSK, SN5S330_ILIM_0_63,
+ NULL);
+}
+
+static void test_sn5s330_set_sbu(void)
+#ifdef CONFIG_USBC_PPC_SBU
+{
+ const struct emul *emul = EMUL;
+ uint8_t func_set2_reg;
+
+ zassert_ok(sn5s330_drv.init(SN5S330_PORT), NULL);
+
+ /* Verify driver enables SBU FET */
+ zassert_ok(sn5s330_drv.set_sbu(SN5S330_PORT, true), NULL);
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET2, &func_set2_reg);
+ zassert_not_equal(func_set2_reg & SN5S330_SBU_EN, 0, NULL);
+
+ /* Verify driver disables SBU FET */
+ zassert_ok(sn5s330_drv.set_sbu(SN5S330_PORT, false), NULL);
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET2, &func_set2_reg);
+ zassert_equal(func_set2_reg & SN5S330_SBU_EN, 0, NULL);
+}
+#else
+{
+ ztest_test_skip();
+}
+#endif /* CONFIG_USBC_PPC_SBU */
+
+static void test_sn5s330_vbus_overcurrent(void)
+{
+ const struct emul *emul = EMUL;
+ uint8_t int_trip_rise_reg1;
+
+ zassert_ok(sn5s330_drv.init(SN5S330_PORT), NULL);
+
+ sn5s330_emul_make_vbus_overcurrent(emul);
+ /*
+ * TODO(b/201420132): Replace arbitrary sleeps.
+ */
+ /* Make sure interrupt happens first. */
+ k_msleep(SN5S330_INTERRUPT_DELAYMS);
+ zassert_true(sn5s330_emul_interrupt_set_stub_fake.call_count > 0, NULL);
+
+ /*
+ * Verify we cleared vbus overcurrent interrupt trip rise bit so the
+ * driver can detect future overcurrent clamping interrupts.
+ */
+ sn5s330_emul_peek_reg(emul, SN5S330_INT_TRIP_RISE_REG1,
+ &int_trip_rise_reg1);
+ zassert_equal(int_trip_rise_reg1 & SN5S330_ILIM_PP1_MASK, 0, NULL);
+}
+
+static void test_sn5s330_disable_vbus_low_interrupt(void)
+#ifdef CONFIG_USBC_PPC_VCONN
+{
+ const struct emul *emul = EMUL;
+
+ /* Interrupt disabled here */
+ zassert_ok(sn5s330_drv.init(SN5S330_PORT), NULL);
+ /* Would normally cause a vbus low interrupt */
+ sn5s330_emul_lower_vbus_below_minv(emul);
+ zassert_equal(sn5s330_emul_interrupt_set_stub_fake.call_count, 0, NULL);
+}
+#else
+{
+ ztest_test_skip();
+}
+#endif /* CONFIG_USBC_PPC_VCONN */
+
+static void test_sn5s330_set_vconn_fet(void)
+{
+ const struct emul *emul = EMUL;
+ uint8_t func_set4_reg;
+
+ zassert_ok(sn5s330_drv.init(SN5S330_PORT), NULL);
+
+ sn5s330_drv.set_vconn(SN5S330_PORT, false);
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET4, &func_set4_reg);
+ zassert_equal(func_set4_reg & SN5S330_VCONN_EN, 0, NULL);
+
+ sn5s330_drv.set_vconn(SN5S330_PORT, true);
+ sn5s330_emul_peek_reg(emul, SN5S330_FUNC_SET4, &func_set4_reg);
+ zassert_not_equal(func_set4_reg & SN5S330_VCONN_EN, 0, NULL);
+}
+
static void reset_sn5s330_state(void)
{
+ struct i2c_emul *i2c_emul = sn5s330_emul_to_i2c_emul(EMUL);
+
+ i2c_common_emul_set_write_func(i2c_emul, NULL, NULL);
+ i2c_common_emul_set_read_func(i2c_emul, NULL, NULL);
sn5s330_emul_reset(EMUL);
+ RESET_FAKE(sn5s330_emul_interrupt_set_stub);
}
void test_suite_ppc_sn5s330(void)
{
- ztest_test_suite(ppc_sn5s330,
- ztest_unit_test_setup_teardown(
- test_fail_once_func_set1, reset_sn5s330_state,
- reset_sn5s330_state));
+ ztest_test_suite(
+ ppc_sn5s330,
+ ztest_unit_test_setup_teardown(test_sn5s330_set_vconn_fet,
+ reset_sn5s330_state,
+ reset_sn5s330_state),
+ ztest_unit_test_setup_teardown(
+ test_sn5s330_disable_vbus_low_interrupt,
+ reset_sn5s330_state, reset_sn5s330_state),
+ ztest_unit_test_setup_teardown(test_sn5s330_vbus_overcurrent,
+ reset_sn5s330_state,
+ reset_sn5s330_state),
+ ztest_unit_test_setup_teardown(test_sn5s330_set_sbu,
+ reset_sn5s330_state,
+ reset_sn5s330_state),
+ ztest_unit_test_setup_teardown(
+ test_set_vbus_source_current_limit, reset_sn5s330_state,
+ reset_sn5s330_state),
+ ztest_unit_test_setup_teardown(test_vbus_discharge,
+ reset_sn5s330_state,
+ reset_sn5s330_state),
+ ztest_unit_test_setup_teardown(test_vbus_source_sink_enable,
+ reset_sn5s330_state,
+ reset_sn5s330_state),
+ ztest_unit_test_setup_teardown(test_enter_low_power_mode,
+ reset_sn5s330_state,
+ reset_sn5s330_state),
+ ztest_unit_test_setup_teardown(
+ test_dead_battery_boot_force_pp2_fets_set,
+ reset_sn5s330_state, reset_sn5s330_state),
+ ztest_unit_test_setup_teardown(test_fail_once_func_set1,
+ reset_sn5s330_state,
+ reset_sn5s330_state));
ztest_run_test_suite(ppc_sn5s330);
}
diff --git a/zephyr/test/drivers/src/ps8xxx.c b/zephyr/test/drivers/src/ps8xxx.c
index 790eebf2db..a2052b43fc 100644
--- a/zephyr/test/drivers/src/ps8xxx.c
+++ b/zephyr/test/drivers/src/ps8xxx.c
@@ -8,8 +8,8 @@
#include "common.h"
#include "emul/emul_common_i2c.h"
-#include "emul/emul_tcpci.h"
-#include "emul/emul_ps8xxx.h"
+#include "emul/tcpc/emul_tcpci.h"
+#include "emul/tcpc/emul_ps8xxx.h"
#include "timer.h"
#include "i2c.h"
#include "stubs.h"
@@ -911,7 +911,14 @@ static void test_ps8xxx_tcpci_low_power_mode(void)
{
const struct emul *ps8xxx_emul = emul_get_binding(PS8XXX_EMUL_LABEL);
const struct emul *tcpci_emul = ps8xxx_emul_get_tcpci(ps8xxx_emul);
-
+ /*
+ * PS8751/PS8815 has the auto sleep function that enters
+ * low power mode on its own in ~2 seconds. Other chips
+ * don't have it. Stub it out for PS8751/PS8815.
+ */
+ if (board_get_ps8xxx_product_id(USBC_PORT_C1) == PS8751_PRODUCT_ID ||
+ board_get_ps8xxx_product_id(USBC_PORT_C1) == PS8815_PRODUCT_ID)
+ return;
test_tcpci_low_power_mode(tcpci_emul, USBC_PORT_C1);
}
diff --git a/zephyr/test/drivers/src/stubs.c b/zephyr/test/drivers/src/stubs.c
index 68aab8ba12..85c528a5bd 100644
--- a/zephyr/test/drivers/src/stubs.c
+++ b/zephyr/test/drivers/src/stubs.c
@@ -11,6 +11,7 @@
#include "charger/isl923x_public.h"
#include "charger/isl9241_public.h"
#include "config.h"
+#include "fff.h"
#include "hooks.h"
#include "i2c/i2c.h"
#include "power.h"
@@ -23,6 +24,13 @@
#include "usb_mux.h"
#include "usb_pd_tcpm.h"
#include "usbc_ppc.h"
+#include "charge_state_v2.h"
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(stubs);
+
+#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
+#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args)
/* All of these definitions are just to get the test to link. None of these
* functions are useful or behave as they should. Please remove them once the
@@ -105,6 +113,56 @@ const enum battery_type DEFAULT_BATTERY_TYPE = BATTERY_LGC011;
int board_set_active_charge_port(int port)
{
+ int is_real_port = (port >= 0 &&
+ port < CONFIG_USB_PD_PORT_MAX_COUNT);
+ int i;
+
+ if (!is_real_port && port != CHARGE_PORT_NONE)
+ return EC_ERROR_INVAL;
+
+ if (port == CHARGE_PORT_NONE) {
+ CPRINTS("Disabling all charging port");
+
+ /* Disable all ports. */
+ for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) {
+ /*
+ * Do not return early if one fails otherwise we can
+ * get into a boot loop assertion failure.
+ */
+ if (board_vbus_sink_enable(i, 0))
+ CPRINTS("Disabling p%d sink path failed.", i);
+ }
+
+ return EC_SUCCESS;
+ }
+
+ /* Check if the port is sourcing VBUS. */
+ if (board_is_sourcing_vbus(port)) {
+ CPRINTS("Skip enable p%d", port);
+ return EC_ERROR_INVAL;
+ }
+
+
+ CPRINTS("New charge port: p%d", port);
+
+ /*
+ * Turn off the other ports' sink path FETs, before enabling the
+ * requested charge port.
+ */
+ for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) {
+ if (i == port)
+ continue;
+
+ if (board_vbus_sink_enable(i, 0))
+ CPRINTS("p%d: sink path disable failed.", i);
+ }
+
+ /* Enable requested charge port. */
+ if (board_vbus_sink_enable(port, 1)) {
+ CPRINTS("p%d: sink path enable failed.", port);
+ return EC_ERROR_UNKNOWN;
+ }
+
return EC_SUCCESS;
}
@@ -116,6 +174,8 @@ int board_is_vbus_too_low(int port, enum chg_ramp_vbus_state ramp_state)
void board_set_charge_limit(int port, int supplier, int charge_ma, int max_ma,
int charge_mv)
{
+ charge_set_input_current_limit(
+ MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT), charge_mv);
}
struct tcpc_config_t tcpc_config[] = {
@@ -156,9 +216,16 @@ void board_set_ps8xxx_product_id(uint16_t product_id)
ps8xxx_product_id = product_id;
}
+int board_vbus_sink_enable(int port, int enable)
+{
+ /* Both ports are controlled by PPC SN5S330 */
+ return ppc_vbus_sink_enable(port, enable);
+}
+
int board_is_sourcing_vbus(int port)
{
- return 0;
+ /* Both ports are controlled by PPC SN5S330 */
+ return ppc_is_sourcing_vbus(port);
}
struct usb_mux usbc0_virtual_usb_mux = {
@@ -235,9 +302,7 @@ struct ppc_config_t ppc_chips[] = {
BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT);
unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips);
-void system_hibernate(uint32_t seconds, uint32_t microseconds)
-{
-}
+DEFINE_FAKE_VOID_FUNC(system_hibernate, uint32_t, uint32_t);
uint16_t tcpc_get_alert_status(void)
{
@@ -265,17 +330,53 @@ enum power_state power_chipset_init(void)
return POWER_G3;
}
-enum power_state mock_state = POWER_G3;
+static enum power_state forced_state;
+static bool force_state;
-void set_mock_power_state(enum power_state state)
+void force_power_state(bool force, enum power_state state)
{
- mock_state = state;
- task_wake(TASK_ID_CHIPSET);
+ forced_state = state;
+ force_state = force;
+
+ if (force) {
+ task_wake(TASK_ID_CHIPSET);
+ /*
+ * TODO(b/201420132) - setting power state requires to wake up
+ * TASK_ID_CHIPSET Sleep is required to run chipset task before
+ * continuing with test
+ */
+ k_msleep(1);
+ }
}
enum power_state power_handle_state(enum power_state state)
{
- return mock_state;
+ switch (state) {
+ case POWER_G3S5:
+ case POWER_S5S3:
+ case POWER_S3S0:
+ case POWER_S0S3:
+ case POWER_S3S5:
+ case POWER_S5G3:
+#ifdef CONFIG_POWER_S0IX
+ case POWER_S0ixS0:
+ case POWER_S0S0ix:
+#endif
+ /*
+ * Wait for event in transition states to prevent dead loop in
+ * chipset task
+ */
+ task_wait_event(-1);
+ break;
+ default:
+ break;
+ }
+
+ if (force_state) {
+ state = forced_state;
+ }
+
+ return state;
}
void chipset_reset(enum chipset_shutdown_reason reason)
@@ -307,10 +408,24 @@ void tcpc_alert_event(enum gpio_signal signal)
schedule_deferred_pd_interrupt(port);
}
+void ppc_alert(enum gpio_signal signal)
+{
+ switch (signal) {
+ case GPIO_USB_C0_PPC_INT_ODL:
+ ppc_chips[USBC_PORT_C0].drv->interrupt(USBC_PORT_C0);
+ break;
+ case GPIO_USB_C1_PPC_INT_ODL:
+ ppc_chips[USBC_PORT_C1].drv->interrupt(USBC_PORT_C1);
+ break;
+ default:
+ return;
+ }
+}
+
/* TODO: This code should really be generic, and run based on something in
* the dts.
*/
-static void usbc_interrupt_init(void)
+static void stubs_interrupt_init(void)
{
/* Enable TCPC interrupts. */
gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL);
@@ -328,5 +443,12 @@ static void usbc_interrupt_init(void)
gpio_set_level(GPIO_USB_C1_TCPC_RST_L, 0);
msleep(PS8XXX_RESET_DELAY_MS);
gpio_set_level(GPIO_USB_C1_TCPC_RST_L, 1);
+
+ /* Enable PPC interrupts. */
+ gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL);
+ gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL);
+
+ /* Enable SwitchCap interrupt */
+ gpio_enable_interrupt(GPIO_SWITCHCAP_PG_INT_L);
}
-DECLARE_HOOK(HOOK_INIT, usbc_interrupt_init, HOOK_PRIO_INIT_I2C + 1);
+DECLARE_HOOK(HOOK_INIT, stubs_interrupt_init, HOOK_PRIO_INIT_I2C + 1);
diff --git a/zephyr/test/drivers/src/tcpci.c b/zephyr/test/drivers/src/tcpci.c
index d67680bacc..cdc13861ab 100644
--- a/zephyr/test/drivers/src/tcpci.c
+++ b/zephyr/test/drivers/src/tcpci.c
@@ -11,7 +11,7 @@
#include "common.h"
#include "ec_tasks.h"
#include "emul/emul_common_i2c.h"
-#include "emul/emul_tcpci.h"
+#include "emul/tcpc/emul_tcpci.h"
#include "hooks.h"
#include "i2c.h"
#include "stubs.h"
@@ -295,8 +295,9 @@ static void test_generic_tcpci_mux_init(void)
zassert_equal(EC_ERROR_TIMEOUT,
tcpci_tcpm_mux_init(tcpci_usb_mux), NULL);
- /* Set correct power status for rest of the test */
- tcpci_emul_set_reg(emul, TCPC_REG_POWER_STATUS, 0);
+ /* Set default power status for rest of the test */
+ tcpci_emul_set_reg(emul, TCPC_REG_POWER_STATUS,
+ TCPC_REG_POWER_STATUS_VBUS_DET);
/* Test fail on alert mask write fail */
i2c_common_emul_set_write_fail_reg(i2c_emul, TCPC_REG_ALERT_MASK);
diff --git a/zephyr/test/drivers/src/tcpci_test_common.c b/zephyr/test/drivers/src/tcpci_test_common.c
index 57cc35b89c..a2925bf3be 100644
--- a/zephyr/test/drivers/src/tcpci_test_common.c
+++ b/zephyr/test/drivers/src/tcpci_test_common.c
@@ -8,7 +8,7 @@
#include "common.h"
#include "emul/emul_common_i2c.h"
-#include "emul/emul_tcpci.h"
+#include "emul/tcpc/emul_tcpci.h"
#include "tcpci_test_common.h"
#include "tcpm/tcpci.h"
@@ -57,7 +57,8 @@ void test_tcpci_init(const struct emul *emul, enum usbc_port port)
TCPC_REG_ALERT_FAULT | TCPC_REG_ALERT_POWER_STATUS;
/* Set TCPCI emulator VBUS to safe0v (disconnected) */
- tcpci_emul_set_reg(emul, TCPC_REG_POWER_STATUS, 0);
+ tcpci_emul_set_reg(emul, TCPC_REG_POWER_STATUS,
+ TCPC_REG_POWER_STATUS_VBUS_DET);
/* Test init with VBUS safe0v without vSafe0V tcpc config flag */
zassert_equal(EC_SUCCESS, drv->init(port), NULL);
@@ -69,7 +70,8 @@ void test_tcpci_init(const struct emul *emul, enum usbc_port port)
/* Set TCPCI emulator VBUS to present (connected, above 4V) */
tcpci_emul_set_reg(emul, TCPC_REG_POWER_STATUS,
- TCPC_REG_POWER_STATUS_VBUS_PRES);
+ TCPC_REG_POWER_STATUS_VBUS_PRES |
+ TCPC_REG_POWER_STATUS_VBUS_DET);
/* Test init with VBUS present without vSafe0V tcpc config flag */
zassert_equal(EC_SUCCESS, drv->init(port), NULL);
@@ -92,7 +94,8 @@ void test_tcpci_init(const struct emul *emul, enum usbc_port port)
check_tcpci_reg(emul, TCPC_REG_ALERT_MASK, exp_mask);
/* Set TCPCI emulator VBUS to safe0v (disconnected) */
- tcpci_emul_set_reg(emul, TCPC_REG_POWER_STATUS, 0);
+ tcpci_emul_set_reg(emul, TCPC_REG_POWER_STATUS,
+ TCPC_REG_POWER_STATUS_VBUS_DET);
tcpci_emul_set_reg(emul, TCPC_REG_EXT_STATUS,
TCPC_REG_EXT_STATUS_SAFE0V);
diff --git a/zephyr/test/drivers/src/usb_mux.c b/zephyr/test/drivers/src/usb_mux.c
index cf6190eec9..517bb59107 100644
--- a/zephyr/test/drivers/src/usb_mux.c
+++ b/zephyr/test/drivers/src/usb_mux.c
@@ -14,6 +14,7 @@
#include "common.h"
#include "ec_commands.h"
#include "ec_tasks.h"
+#include "fff.h"
#include "hooks.h"
#include "host_command.h"
#include "i2c.h"
@@ -27,86 +28,151 @@
/** Copy of original usb_muxes[USB_PORT_C1] */
struct usb_mux usb_mux_c1;
+/** Number of usb mux proxies in chain */
+#define NUM_OF_PROXY 3
+
/** Pointers to original usb muxes chain of port c1 */
-const struct usb_mux *org_mux[3];
+const struct usb_mux *org_mux[NUM_OF_PROXY];
/** Proxy function which check calls from usb_mux framework to driver */
-static int proxy_init(const struct usb_mux *me)
+FAKE_VALUE_FUNC1(int, proxy_init, const struct usb_mux *);
+static int proxy_init_custom(const struct usb_mux *me)
{
int i = me->i2c_addr_flags;
+ int ec = EC_SUCCESS;
- ztest_check_expected_value(i);
+ zassert_true(i < NUM_OF_PROXY, "Proxy called for non proxy usb_mux");
if (org_mux[i] != NULL &&
org_mux[i]->driver->init != NULL) {
- org_mux[i]->driver->init(org_mux[i]);
+ ec = org_mux[i]->driver->init(org_mux[i]);
+ }
+
+ if (task_get_current() == TASK_ID_TEST_RUNNER) {
+ RETURN_FAKE_RESULT(proxy_init);
}
- return ztest_get_return_value();
+ /* Discard this call if made from different thread */
+ proxy_init_fake.call_count--;
+
+ return ec;
}
/** Proxy function which check calls from usb_mux framework to driver */
-static int proxy_set(const struct usb_mux *me, mux_state_t mux_state,
- bool *ack_required)
+FAKE_VALUE_FUNC3(int, proxy_set, const struct usb_mux *, mux_state_t, bool *);
+static int proxy_set_custom(const struct usb_mux *me, mux_state_t mux_state,
+ bool *ack_required)
{
int i = me->i2c_addr_flags;
+ int ec = EC_SUCCESS;
- ztest_check_expected_value(i);
- ztest_check_expected_value(mux_state);
+ zassert_true(i < NUM_OF_PROXY, "Proxy called for non proxy usb_mux");
if (org_mux[i] != NULL &&
org_mux[i]->driver->set != NULL) {
- org_mux[i]->driver->set(org_mux[i], mux_state, ack_required);
+ ec = org_mux[i]->driver->set(org_mux[i], mux_state,
+ ack_required);
}
- return ztest_get_return_value();
+ if (task_get_current() == TASK_ID_TEST_RUNNER) {
+ RETURN_FAKE_RESULT(proxy_set);
+ }
+
+ /* Discard this call if made from different thread */
+ proxy_set_fake.call_count--;
+
+ return ec;
}
/** Proxy function which check calls from usb_mux framework to driver */
-static int proxy_get(const struct usb_mux *me, mux_state_t *mux_state)
+FAKE_VALUE_FUNC2(int, proxy_get, const struct usb_mux *, mux_state_t *);
+/** Sequence of mux_state values returned by proxy_get function */
+static mux_state_t proxy_get_mux_state_seq[NUM_OF_PROXY];
+/** Index of next mux_state to return from proxy_get_function */
+static int proxy_get_mux_state_seq_idx;
+/** Set all mux_state in sequence to the same state value */
+static void set_proxy_get_mux_state_seq(mux_state_t state)
+{
+ proxy_get_mux_state_seq_idx = 0;
+ for (int i = 0; i < NUM_OF_PROXY; i++) {
+ proxy_get_mux_state_seq[i] = state;
+ }
+}
+
+static int proxy_get_custom(const struct usb_mux *me, mux_state_t *mux_state)
{
int i = me->i2c_addr_flags;
+ int ec = EC_SUCCESS;
- ztest_check_expected_value(i);
+ zassert_true(i < NUM_OF_PROXY, "Proxy called for non proxy usb_mux");
if (org_mux[i] != NULL &&
org_mux[i]->driver->get != NULL) {
- org_mux[i]->driver->get(org_mux[i], mux_state);
+ ec = org_mux[i]->driver->get(org_mux[i], mux_state);
+ }
+
+ if (task_get_current() == TASK_ID_TEST_RUNNER) {
+ zassert_true(proxy_get_mux_state_seq_idx < NUM_OF_PROXY,
+ "%s called too many times without resetting "
+ "mux_state_seq", __func__);
+ *mux_state =
+ proxy_get_mux_state_seq[proxy_get_mux_state_seq_idx];
+ proxy_get_mux_state_seq_idx++;
+ RETURN_FAKE_RESULT(proxy_get);
}
- *mux_state = ztest_get_return_value();
+ /* Discard this call if made from different thread */
+ proxy_get_fake.call_count--;
- return ztest_get_return_value();
+ return ec;
}
/** Proxy function which check calls from usb_mux framework to driver */
-static int proxy_enter_low_power_mode(const struct usb_mux *me)
+FAKE_VALUE_FUNC1(int, proxy_enter_low_power_mode, const struct usb_mux *);
+static int proxy_enter_low_power_mode_custom(const struct usb_mux *me)
{
int i = me->i2c_addr_flags;
+ int ec = EC_SUCCESS;
- ztest_check_expected_value(i);
+ zassert_true(i < NUM_OF_PROXY, "Proxy called for non proxy usb_mux");
if (org_mux[i] != NULL &&
org_mux[i]->driver->enter_low_power_mode != NULL) {
- org_mux[i]->driver->enter_low_power_mode(org_mux[i]);
+ ec = org_mux[i]->driver->enter_low_power_mode(org_mux[i]);
}
- return ztest_get_return_value();
+ if (task_get_current() == TASK_ID_TEST_RUNNER) {
+ RETURN_FAKE_RESULT(proxy_enter_low_power_mode);
+ }
+
+ /* Discard this call if made from different thread */
+ proxy_enter_low_power_mode_fake.call_count--;
+
+ return ec;
}
/** Proxy function which check calls from usb_mux framework to driver */
-static int proxy_chipset_reset(const struct usb_mux *me)
+FAKE_VALUE_FUNC1(int, proxy_chipset_reset, const struct usb_mux *);
+static int proxy_chipset_reset_custom(const struct usb_mux *me)
{
int i = me->i2c_addr_flags;
+ int ec = EC_SUCCESS;
- ztest_check_expected_value(i);
+ zassert_true(i < NUM_OF_PROXY, "Proxy called for non proxy usb_mux");
if (org_mux[i] != NULL &&
org_mux[i]->driver->chipset_reset != NULL) {
- org_mux[i]->driver->chipset_reset(org_mux[i]);
+ ec = org_mux[i]->driver->chipset_reset(org_mux[i]);
}
- return ztest_get_return_value();
+ if (task_get_current() == TASK_ID_TEST_RUNNER) {
+ RETURN_FAKE_RESULT(proxy_chipset_reset);
+ }
+
+ /* Discard this call if made from different thread */
+ proxy_chipset_reset_fake.call_count--;
+
+ return ec;
}
/** Proxy function for fw update capability */
@@ -116,16 +182,22 @@ static bool proxy_fw_update_cap(void)
}
/** Proxy function which check calls from usb_mux framework to driver */
-static void proxy_hpd_update(const struct usb_mux *me, mux_state_t mux_state)
+FAKE_VOID_FUNC3(proxy_hpd_update, const struct usb_mux *, mux_state_t, bool *);
+static void proxy_hpd_update_custom(const struct usb_mux *me,
+ mux_state_t mux_state, bool *ack_required)
{
int i = me->i2c_addr_flags;
- ztest_check_expected_value(i);
- ztest_check_expected_value(mux_state);
+ zassert_true(i < NUM_OF_PROXY, "Proxy called for non proxy usb_mux");
if (org_mux[i] != NULL &&
org_mux[i]->hpd_update != NULL) {
- org_mux[i]->hpd_update(org_mux[i], mux_state);
+ org_mux[i]->hpd_update(org_mux[i], mux_state, ack_required);
+ }
+
+ if (task_get_current() != TASK_ID_TEST_RUNNER) {
+ /* Discard this call if made from different thread */
+ proxy_hpd_update_fake.call_count--;
}
}
@@ -139,6 +211,71 @@ const struct usb_mux_driver proxy_usb_mux = {
.is_retimer_fw_update_capable = &proxy_fw_update_cap,
};
+/** Mock function used in init test */
+FAKE_VALUE_FUNC1(int, mock_board_init, const struct usb_mux *);
+static int mock_board_init_custom(const struct usb_mux *me)
+{
+ if (task_get_current() == TASK_ID_TEST_RUNNER) {
+ RETURN_FAKE_RESULT(mock_board_init);
+ }
+
+ /* Discard this call if made from different thread */
+ mock_board_init_fake.call_count--;
+
+ return EC_SUCCESS;
+}
+
+/** Mock function used in set test */
+FAKE_VALUE_FUNC2(int, mock_board_set, const struct usb_mux *, mux_state_t);
+static int mock_board_set_custom(const struct usb_mux *me,
+ mux_state_t mux_state)
+{
+ if (task_get_current() == TASK_ID_TEST_RUNNER) {
+ RETURN_FAKE_RESULT(mock_board_set);
+ }
+
+ /* Discard this call if made from different thread */
+ mock_board_set_fake.call_count--;
+
+ return EC_SUCCESS;
+}
+
+/**
+ * Reset state of all fake functions, setup custom fake functions and set
+ * default return value to EC_SUCCESS (all functions which has return value)
+ */
+static void reset_proxy_fakes(void)
+{
+ RESET_FAKE(proxy_init);
+ RESET_FAKE(proxy_set);
+ RESET_FAKE(proxy_get);
+ RESET_FAKE(proxy_enter_low_power_mode);
+ RESET_FAKE(proxy_chipset_reset);
+ RESET_FAKE(proxy_hpd_update);
+ RESET_FAKE(mock_board_init);
+ RESET_FAKE(mock_board_set);
+
+ /* Setup proxy functions */
+ proxy_init_fake.custom_fake = proxy_init_custom;
+ proxy_set_fake.custom_fake = proxy_set_custom;
+ proxy_get_fake.custom_fake = proxy_get_custom;
+ proxy_enter_low_power_mode_fake.custom_fake =
+ proxy_enter_low_power_mode_custom;
+ proxy_chipset_reset_fake.custom_fake = proxy_chipset_reset_custom;
+ proxy_hpd_update_fake.custom_fake = proxy_hpd_update_custom;
+ mock_board_init_fake.custom_fake = mock_board_init_custom;
+ mock_board_set_fake.custom_fake = mock_board_set_custom;
+
+ /* Set default return value */
+ proxy_init_fake.return_val = EC_SUCCESS;
+ proxy_set_fake.return_val = EC_SUCCESS;
+ proxy_get_fake.return_val = EC_SUCCESS;
+ proxy_enter_low_power_mode_fake.return_val = EC_SUCCESS;
+ proxy_chipset_reset_fake.return_val = EC_SUCCESS;
+ mock_board_init_fake.return_val = EC_SUCCESS;
+ mock_board_set_fake.return_val = EC_SUCCESS;
+}
+
/** Chain of 3 proxy usb muxes */
struct usb_mux proxy_chain_2 = {
.usb_port = USBC_PORT_C1,
@@ -180,7 +317,7 @@ static void setup_usb_mux_proxy_chain(void)
* each proxy
*/
t = &usb_mux_c1;
- for (i = 0; i < 3; i++) {
+ for (i = 0; i < NUM_OF_PROXY; i++) {
org_mux[i] = t;
if (t != NULL) {
t = t->next_mux;
@@ -194,146 +331,96 @@ static void setup_usb_mux_proxy_chain(void)
}
}
-static void suspend_usbc_task(bool suspend)
-{
- static const task_id_t cros_tids[] = {
- COND_CODE_1(HAS_TASK_PD_C0, (TASK_ID_PD_C0,), ())
- COND_CODE_1(HAS_TASK_PD_C1, (TASK_ID_PD_C1,), ())
- COND_CODE_1(HAS_TASK_PD_C2, (TASK_ID_PD_C2,), ())
- COND_CODE_1(HAS_TASK_PD_C3, (TASK_ID_PD_C3,), ())
- };
-
- for (int i = 0; i < ARRAY_SIZE(cros_tids); ++i)
- /*
- * TODO(b/201420132): pd_set_suspend uses sleeps which we should
- * minimize
- */
- pd_set_suspend(TASK_ID_TO_PD_PORT(cros_tids[i]), suspend);
-}
-
/** Restore original usb_mux chain without proxy */
-static void resotre_usb_mux_chain(void)
+static void restore_usb_mux_chain(void)
{
- suspend_usbc_task(/*suspend=*/ false);
memcpy(&usb_muxes[USBC_PORT_C1], &usb_mux_c1, sizeof(struct usb_mux));
}
/**
- * Setup expect values for proxy from first to last selected.
- * Set value returned by proxy to ec.
- */
-static void setup_ztest_proxy_init(int first, int last, int ec)
-{
- for (int i = first; i <= last; i++) {
- ztest_expect_value(proxy_init, i, i);
- ztest_returns_value(proxy_init, ec);
- }
-}
-
-/**
- * Setup expect values for proxy from first to last selected.
- * Set value returned by proxy to ec.
+ * Check if given proxy function was called num times and if first argument was
+ * pointer to the right proxy chain element. First argument is
+ * const struct usb_mux * for all struct usb_mux_driver callbacks.
*/
-static void setup_ztest_proxy_set(int first, int last, int ec, mux_state_t exp)
-{
- for (int i = first; i <= last; i++) {
- ztest_expect_value(proxy_set, i, i);
- ztest_expect_value(proxy_set, mux_state, exp);
- ztest_returns_value(proxy_set, ec);
- }
-}
+#define CHECK_PROXY_FAKE_CALL_CNT(proxy, num) \
+ do { \
+ zassert_equal(num, proxy##_fake.call_count, "%d != %d", \
+ num, proxy##_fake.call_count); \
+ if (num >= 1) { \
+ zassert_equal(&usb_muxes[USBC_PORT_C1], \
+ proxy##_fake.arg0_history[0], \
+ NULL); \
+ } \
+ if (num >= 2) { \
+ zassert_equal(&proxy_chain_1, \
+ proxy##_fake.arg0_history[1], \
+ NULL); \
+ } \
+ if (num >= 3) { \
+ zassert_equal(&proxy_chain_2, \
+ proxy##_fake.arg0_history[2], \
+ NULL); \
+ } \
+ } while (0)
/**
- * Setup expect values for proxy from first to last selected. Set value
- * returned by proxy to ec and value returned through mux_state to exp.
+ * Do the same thing as CHECK_PROXY_FAKE_CALL_CNT and check if second argument
+ * was the same as given state. hpd_update and set callback have mux_state_t
+ * as second argument.
*/
-static void setup_ztest_proxy_get(int first, int last, int ec, mux_state_t exp)
-{
- for (int i = first; i <= last; i++) {
- ztest_expect_value(proxy_get, i, i);
- ztest_returns_value(proxy_get, exp);
- ztest_returns_value(proxy_get, ec);
- }
-}
-
-/**
- * Setup expect values for proxy from first to last selected.
- * Set value returned by proxy to ec.
- */
-static void setup_ztest_proxy_enter_lpm(int first, int last, int ec)
-{
- for (int i = first; i <= last; i++) {
- ztest_expect_value(proxy_enter_low_power_mode, i, i);
- ztest_returns_value(proxy_enter_low_power_mode, ec);
- }
-}
-
-/**
- * Setup expect values for proxy from first to last selected.
- * Set value returned by proxy to ec.
- */
-static void setup_ztest_proxy_chipset_reset(int first, int last, int ec)
-{
- for (int i = first; i <= last; i++) {
- ztest_expect_value(proxy_chipset_reset, i, i);
- ztest_returns_value(proxy_chipset_reset, ec);
- }
-}
-
-/** Setup expect values for proxy from first to last selected */
-static void setup_ztest_proxy_hpd_update(int first, int last, mux_state_t exp)
-{
- for (int i = first; i <= last; i++) {
- ztest_expect_value(proxy_hpd_update, i, i);
- ztest_expect_value(proxy_hpd_update, mux_state, exp);
- }
-}
-
-/** Mock function used in set test */
-static int mock_board_set(const struct usb_mux *me, mux_state_t mux_state)
-{
- int i = me->i2c_addr_flags;
-
- ztest_check_expected_value(i);
-
- return EC_SUCCESS;
-}
+#define CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy, num, state) \
+ do { \
+ CHECK_PROXY_FAKE_CALL_CNT(proxy, num); \
+ if (num >= 1) { \
+ zassert_equal(state, \
+ proxy##_fake.arg1_history[0], \
+ "0x%x != 0x%x", state, \
+ proxy##_fake.arg1_history[0]); \
+ } \
+ if (num >= 2) { \
+ zassert_equal(state, \
+ proxy##_fake.arg1_history[1], \
+ "0x%x != 0x%x", state, \
+ proxy##_fake.arg1_history[1]); \
+ } \
+ if (num >= 3) { \
+ zassert_equal(state, \
+ proxy##_fake.arg1_history[2], \
+ "0x%x != 0x%x", state, \
+ proxy##_fake.arg1_history[2]); \
+ } \
+ } while (0)
/** Test usb_mux init */
static void test_usb_mux_init(void)
{
+ int fail_on_2nd_ret[] = {EC_SUCCESS, EC_ERROR_NOT_POWERED};
+
/* Set AP to normal state to init BB retimer */
- set_mock_power_state(POWER_S0);
- /*
- * TODO(b/201420132) - setting power state requires to wake up
- * TASK_ID_CHIPSET Sleep is required to run chipset task before
- * continuing with test
- */
- k_msleep(1);
+ power_set_state(POWER_S0);
/* Test successful initialisation */
- setup_ztest_proxy_init(0, 2, EC_SUCCESS);
usb_mux_init(USBC_PORT_C1);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, NUM_OF_PROXY);
/*
* Test failed initialisation. Muxes that are in chain after
* the one which fails shouldn't be called
*/
- setup_ztest_proxy_init(0, 0, EC_SUCCESS);
- setup_ztest_proxy_init(1, 1, EC_ERROR_NOT_POWERED);
+ reset_proxy_fakes();
+ SET_RETURN_SEQ(proxy_init, fail_on_2nd_ret, 2);
usb_mux_init(USBC_PORT_C1);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, 2);
/* Test board init callback */
- proxy_chain_1.board_init = proxy_init;
- setup_ztest_proxy_init(0, 0, EC_SUCCESS);
- /*
- * board_init of second mux mock is set to init mock function, so it
- * should be called two times.
- */
- setup_ztest_proxy_init(1, 1, EC_SUCCESS);
- setup_ztest_proxy_init(1, 2, EC_SUCCESS);
-
+ proxy_chain_1.board_init = &mock_board_init;
+ reset_proxy_fakes();
usb_mux_init(USBC_PORT_C1);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, NUM_OF_PROXY);
+ /* Check if board_init was called for proxy 1 */
+ zassert_equal(1, mock_board_init_fake.call_count, NULL);
+ zassert_equal(&proxy_chain_1, mock_board_init_fake.arg0_history[0],
+ NULL);
proxy_chain_1.board_init = NULL;
}
@@ -341,40 +428,57 @@ static void test_usb_mux_init(void)
/** Test usb_mux setting mux mode */
static void test_usb_mux_set(void)
{
+ int fail_on_2nd_ret[] = {EC_SUCCESS, EC_ERROR_UNKNOWN};
mux_state_t exp_mode;
- /* usb mux 1 shouldn't be set with polarity mode */
+ /* Set flag for usb mux 1 to disable polarity setting */
proxy_chain_1.flags = USB_MUX_FLAG_SET_WITHOUT_FLIP;
/* Test setting mux mode without polarity inversion */
+ reset_proxy_fakes();
exp_mode = USB_PD_MUX_USB_ENABLED;
- setup_ztest_proxy_init(0, 2, EC_SUCCESS);
- setup_ztest_proxy_set(0, 2, EC_SUCCESS, exp_mode);
usb_mux_set(USBC_PORT_C1, exp_mode, USB_SWITCH_CONNECT,
0 /* = polarity */);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, NUM_OF_PROXY);
+ /* All muxes should have the same mode */
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_set, NUM_OF_PROXY, exp_mode);
/* Test setting mux mode with polarity inversion */
+ reset_proxy_fakes();
exp_mode = USB_PD_MUX_TBT_COMPAT_ENABLED;
- setup_ztest_proxy_set(0, 0, EC_SUCCESS,
- exp_mode | USB_PD_MUX_POLARITY_INVERTED);
- setup_ztest_proxy_set(1, 1, EC_SUCCESS, exp_mode);
- setup_ztest_proxy_set(2, 2, EC_SUCCESS,
- exp_mode | USB_PD_MUX_POLARITY_INVERTED);
usb_mux_set(USBC_PORT_C1, exp_mode, USB_SWITCH_CONNECT,
1 /* = polarity */);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, 0);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_set, NUM_OF_PROXY);
+ /* usb mux 1 shouldn't be set with polarity mode, because of flag */
+ zassert_equal(exp_mode | USB_PD_MUX_POLARITY_INVERTED,
+ proxy_set_fake.arg1_history[0], NULL);
+ zassert_equal(exp_mode, proxy_set_fake.arg1_history[1], NULL);
+ zassert_equal(exp_mode | USB_PD_MUX_POLARITY_INVERTED,
+ proxy_set_fake.arg1_history[2], NULL);
/* Test board set callback */
- setup_ztest_proxy_set(0, 2, EC_SUCCESS, exp_mode);
+ reset_proxy_fakes();
proxy_chain_1.board_set = &mock_board_set;
- ztest_expect_value(mock_board_set, i, 1);
usb_mux_set(USBC_PORT_C1, exp_mode, USB_SWITCH_CONNECT,
0 /* = polarity */);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, 0);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_set, NUM_OF_PROXY, exp_mode);
+ /* Check if board_set was called for proxy 1 */
+ zassert_equal(1, mock_board_set_fake.call_count, NULL);
+ zassert_equal(&proxy_chain_1, mock_board_set_fake.arg0_history[0],
+ NULL);
+ zassert_equal(exp_mode, mock_board_set_fake.arg1_history[0], NULL);
/* Test set function with error in usb_mux */
- setup_ztest_proxy_set(0, 0, EC_SUCCESS, exp_mode);
- setup_ztest_proxy_set(1, 1, EC_ERROR_UNKNOWN, exp_mode);
+ reset_proxy_fakes();
+ SET_RETURN_SEQ(proxy_set, fail_on_2nd_ret, 2);
usb_mux_set(USBC_PORT_C1, exp_mode, USB_SWITCH_CONNECT,
0 /* = polarity */);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, 0);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_set, 2, exp_mode);
+ /* board_set shouldn't be called after fail */
+ zassert_equal(0, mock_board_set_fake.call_count, NULL);
proxy_chain_1.board_set = NULL;
}
@@ -385,115 +489,125 @@ static void test_usb_mux_reset_in_g3(void)
mux_state_t exp_mode = USB_PD_MUX_USB_ENABLED;
/* Test that init is called */
- setup_ztest_proxy_init(0, 2, EC_SUCCESS);
- setup_ztest_proxy_set(0, 2, EC_SUCCESS, exp_mode);
+ reset_proxy_fakes();
usb_mux_set(USBC_PORT_C1, exp_mode, USB_SWITCH_CONNECT,
0 /* = polarity */);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, NUM_OF_PROXY);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_set, NUM_OF_PROXY, exp_mode);
/* Usb muxes of port 1 should stay initialised */
usb_muxes[USBC_PORT_C1].flags = 0;
hook_notify(HOOK_CHIPSET_HARD_OFF);
/* Test that init is not called */
- setup_ztest_proxy_set(0, 2, EC_SUCCESS, exp_mode);
+ reset_proxy_fakes();
usb_mux_set(USBC_PORT_C1, exp_mode, USB_SWITCH_CONNECT,
0 /* = polarity */);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, 0);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_set, NUM_OF_PROXY, exp_mode);
}
/** Test usb_mux getting mux mode */
static void test_usb_mux_get(void)
{
+ int fail_on_2nd_ret[] = {EC_SUCCESS, EC_ERROR_UNKNOWN};
mux_state_t exp_mode, mode;
/* Test getting mux mode */
exp_mode = USB_PD_MUX_USB_ENABLED;
- setup_ztest_proxy_init(0, 2, EC_SUCCESS);
- setup_ztest_proxy_get(0, 2, EC_SUCCESS, exp_mode);
+ set_proxy_get_mux_state_seq(exp_mode);
mode = usb_mux_get(USBC_PORT_C1);
zassert_equal(exp_mode, mode, "mode is 0x%x (!= 0x%x)", mode, exp_mode);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, NUM_OF_PROXY);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_get, NUM_OF_PROXY);
- /* Test getting mux mode with one inverted polarisation */
+ /* Test getting mux mode with inverted polarisation in one mux */
+ reset_proxy_fakes();
exp_mode = USB_PD_MUX_TBT_COMPAT_ENABLED;
- setup_ztest_proxy_get(0, 0, EC_SUCCESS, exp_mode);
- setup_ztest_proxy_get(1, 1, EC_SUCCESS,
- exp_mode | USB_PD_MUX_POLARITY_INVERTED);
- setup_ztest_proxy_get(2, 2, EC_SUCCESS, exp_mode);
+ set_proxy_get_mux_state_seq(exp_mode);
+ /* Set polarisation in usb mux 1 state */
+ proxy_get_mux_state_seq[1] |= USB_PD_MUX_POLARITY_INVERTED;
exp_mode |= USB_PD_MUX_POLARITY_INVERTED;
mode = usb_mux_get(USBC_PORT_C1);
zassert_equal(exp_mode, mode, "mode is 0x%x (!= 0x%x)", mode, exp_mode);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, 0);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_get, NUM_OF_PROXY);
/* Test get function with error in usb_mux */
- setup_ztest_proxy_get(0, 0, EC_SUCCESS, USB_PD_MUX_TBT_COMPAT_ENABLED);
- setup_ztest_proxy_get(1, 1, EC_ERROR_UNKNOWN,
- USB_PD_MUX_TBT_COMPAT_ENABLED);
+ reset_proxy_fakes();
+ SET_RETURN_SEQ(proxy_get, fail_on_2nd_ret, 2);
+ set_proxy_get_mux_state_seq(USB_PD_MUX_TBT_COMPAT_ENABLED);
exp_mode = USB_PD_MUX_NONE;
mode = usb_mux_get(USBC_PORT_C1);
zassert_equal(exp_mode, mode, "mode is 0x%x (!= 0x%x)", mode, exp_mode);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, 0);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_get, 2);
}
/** Test usb_mux entering and exiting low power mode */
static void test_usb_mux_low_power_mode(void)
{
+ int fail_on_2nd_ret[] = {EC_SUCCESS, EC_ERROR_NOT_POWERED};
mux_state_t exp_mode, mode;
- /*
- * Virtual mux return ack_required in some cases, but this requires to
- * run usb_mux_set in TASK_PD_C1 context. Remove virtual mux from chain
- * for this test.
- *
- * TODO: Find way to setup PD stack in such state that notifing PD task
- * results in required usb_mux_set call.
- */
- org_mux[1] = NULL;
-
/* Test enter to low power mode */
exp_mode = USB_PD_MUX_NONE;
- setup_ztest_proxy_set(0, 2, EC_SUCCESS, exp_mode);
- setup_ztest_proxy_enter_lpm(0, 2, EC_SUCCESS);
usb_mux_set(USBC_PORT_C1, exp_mode, USB_SWITCH_DISCONNECT,
0 /* = polarity */);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_enter_low_power_mode, NUM_OF_PROXY);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_set, NUM_OF_PROXY, exp_mode);
/* Test that nothing is changed when already in low power mode */
+ reset_proxy_fakes();
exp_mode = USB_PD_MUX_NONE;
usb_mux_set(USBC_PORT_C1, exp_mode, USB_SWITCH_DISCONNECT,
0 /* = polarity */);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_enter_low_power_mode, 0);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_set, 0);
/* Test that get return USB_PD_MUX_NONE in low power mode */
exp_mode = USB_PD_MUX_NONE;
mode = usb_mux_get(USBC_PORT_C1);
zassert_equal(exp_mode, mode, "mode is 0x%x (!= 0x%x)", mode, exp_mode);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_get, 0);
/* Test exiting from low power mode */
+ reset_proxy_fakes();
exp_mode = USB_PD_MUX_USB_ENABLED;
- setup_ztest_proxy_init(0, 2, EC_SUCCESS);
- setup_ztest_proxy_set(0, 2, EC_SUCCESS, exp_mode);
usb_mux_set(USBC_PORT_C1, exp_mode, USB_SWITCH_CONNECT,
0 /* = polarity */);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, NUM_OF_PROXY);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_set, NUM_OF_PROXY, exp_mode);
/* Test exiting from lpm, when init end with EC_ERROR_NOT_POWERED */
- setup_ztest_proxy_init(0, 0, EC_SUCCESS);
- setup_ztest_proxy_init(1, 1, EC_ERROR_NOT_POWERED);
+ reset_proxy_fakes();
+ SET_RETURN_SEQ(proxy_init, fail_on_2nd_ret, 2);
usb_mux_init(USBC_PORT_C1);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, 2);
+ reset_proxy_fakes();
exp_mode = USB_PD_MUX_USB_ENABLED;
- setup_ztest_proxy_init(0, 2, EC_SUCCESS);
- setup_ztest_proxy_set(0, 2, EC_SUCCESS, exp_mode);
usb_mux_set(USBC_PORT_C1, exp_mode, USB_SWITCH_CONNECT,
0 /* = polarity */);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, NUM_OF_PROXY);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_set, NUM_OF_PROXY, exp_mode);
/* Test enter to low power mode with polarity */
+ reset_proxy_fakes();
exp_mode = USB_PD_MUX_NONE;
- setup_ztest_proxy_set(0, 2, EC_SUCCESS, exp_mode);
- setup_ztest_proxy_enter_lpm(0, 2, EC_SUCCESS);
usb_mux_set(USBC_PORT_C1, exp_mode, USB_SWITCH_DISCONNECT,
1 /* = polarity */);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_enter_low_power_mode, NUM_OF_PROXY);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_set, NUM_OF_PROXY, exp_mode);
/* Test that nothing is changed on lpm exit error */
+ reset_proxy_fakes();
+ SET_RETURN_SEQ(proxy_init, fail_on_2nd_ret, 2);
exp_mode = USB_PD_MUX_USB_ENABLED;
- setup_ztest_proxy_init(0, 0, EC_SUCCESS);
- setup_ztest_proxy_init(1, 1, EC_ERROR_NOT_POWERED);
usb_mux_set(USBC_PORT_C1, exp_mode, USB_SWITCH_CONNECT,
0 /* = polarity */);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, 2);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_set, 0);
}
/** Test usb_mux flip */
@@ -501,32 +615,34 @@ static void test_usb_mux_flip(void)
{
mux_state_t exp_mode;
- /* usb mux mock 1 shouldn't be set with polarity mode */
+ /* Set flag for usb mux 1 to disable polarity setting */
proxy_chain_1.flags = USB_MUX_FLAG_SET_WITHOUT_FLIP;
- /* Makes sure that usb muxes of port 1 are not init */
- usb_muxes[USBC_PORT_C1].flags = USB_MUX_FLAG_RESETS_IN_G3;
- hook_notify(HOOK_CHIPSET_HARD_OFF);
-
/* Test flip port without polarity inverted */
exp_mode = USB_PD_MUX_USB_ENABLED;
- setup_ztest_proxy_init(0, 2, EC_SUCCESS);
- setup_ztest_proxy_get(0, 2, EC_SUCCESS, exp_mode);
- exp_mode |= USB_PD_MUX_POLARITY_INVERTED;
- setup_ztest_proxy_set(0, 0, EC_SUCCESS, exp_mode);
- setup_ztest_proxy_set(1, 1, EC_SUCCESS,
- exp_mode & ~USB_PD_MUX_POLARITY_INVERTED);
- setup_ztest_proxy_set(2, 2, EC_SUCCESS, exp_mode);
+ set_proxy_get_mux_state_seq(exp_mode);
usb_mux_flip(USBC_PORT_C1);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, NUM_OF_PROXY);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_get, NUM_OF_PROXY);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_set, NUM_OF_PROXY);
+ /* usb mux 1 shouldn't be set with polarity mode, because of flag */
+ zassert_equal(exp_mode | USB_PD_MUX_POLARITY_INVERTED,
+ proxy_set_fake.arg1_history[0], NULL);
+ zassert_equal(exp_mode, proxy_set_fake.arg1_history[1], NULL);
+ zassert_equal(exp_mode | USB_PD_MUX_POLARITY_INVERTED,
+ proxy_set_fake.arg1_history[2], NULL);
/* Test flip port with polarity inverted */
- setup_ztest_proxy_get(0, 0, EC_SUCCESS, exp_mode);
- setup_ztest_proxy_get(1, 1, EC_SUCCESS,
- exp_mode & ~USB_PD_MUX_POLARITY_INVERTED);
- setup_ztest_proxy_get(2, 2, EC_SUCCESS, exp_mode);
+ reset_proxy_fakes();
+ exp_mode |= USB_PD_MUX_POLARITY_INVERTED;
+ set_proxy_get_mux_state_seq(exp_mode);
+ /* Clear polarity bit from usb mux 1 */
+ proxy_get_mux_state_seq[1] &= ~USB_PD_MUX_POLARITY_INVERTED;
exp_mode &= ~USB_PD_MUX_POLARITY_INVERTED;
- setup_ztest_proxy_set(0, 2, EC_SUCCESS, exp_mode);
usb_mux_flip(USBC_PORT_C1);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, 0);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_get, NUM_OF_PROXY);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_set, NUM_OF_PROXY, exp_mode);
}
void test_usb_mux_hpd_update(void)
@@ -538,40 +654,50 @@ void test_usb_mux_hpd_update(void)
/* Test no hpd level and no irq */
exp_mode = virt_mode;
- setup_ztest_proxy_init(0, 2, EC_SUCCESS);
- setup_ztest_proxy_hpd_update(0, 2, exp_mode);
usb_mux_hpd_update(USBC_PORT_C1, exp_mode);
/* Check if virtual usb mux mode is updated correctly */
usbc1_virtual_usb_mux.driver->get(&usbc1_virtual_usb_mux, &mode);
zassert_equal(exp_mode, mode, "virtual mux mode is 0x%x (!= 0x%x)",
mode, exp_mode);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, NUM_OF_PROXY);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_hpd_update, NUM_OF_PROXY,
+ exp_mode);
/* Test hpd level and irq */
+ reset_proxy_fakes();
exp_mode = virt_mode | USB_PD_MUX_HPD_LVL | USB_PD_MUX_HPD_IRQ;
- setup_ztest_proxy_hpd_update(0, 2, exp_mode);
usb_mux_hpd_update(USBC_PORT_C1, exp_mode);
/* Check if virtual usb mux mode is updated correctly */
usbc1_virtual_usb_mux.driver->get(&usbc1_virtual_usb_mux, &mode);
zassert_equal(exp_mode, mode, "virtual mux mode is 0x%x (!= 0x%x)",
mode, exp_mode);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, 0);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_hpd_update, NUM_OF_PROXY,
+ exp_mode);
/* Test no hpd level and irq */
+ reset_proxy_fakes();
exp_mode = virt_mode | USB_PD_MUX_HPD_IRQ;
- setup_ztest_proxy_hpd_update(0, 2, exp_mode);
usb_mux_hpd_update(USBC_PORT_C1, exp_mode);
/* Check if virtual usb mux mode is updated correctly */
usbc1_virtual_usb_mux.driver->get(&usbc1_virtual_usb_mux, &mode);
zassert_equal(exp_mode, mode, "virtual mux mode is 0x%x (!= 0x%x)",
mode, exp_mode);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, 0);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_hpd_update, NUM_OF_PROXY,
+ exp_mode);
/* Test hpd level and no irq */
+ reset_proxy_fakes();
exp_mode = virt_mode | USB_PD_MUX_HPD_LVL;
- setup_ztest_proxy_hpd_update(0, 2, exp_mode);
usb_mux_hpd_update(USBC_PORT_C1, exp_mode);
/* Check if virtual usb mux mode is updated correctly */
usbc1_virtual_usb_mux.driver->get(&usbc1_virtual_usb_mux, &mode);
zassert_equal(exp_mode, mode, "virtual mux mode is 0x%x (!= 0x%x)",
mode, exp_mode);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, 0);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_hpd_update, NUM_OF_PROXY,
+ exp_mode);
}
void test_usb_mux_fw_update_port_info(void)
@@ -585,9 +711,9 @@ void test_usb_mux_fw_update_port_info(void)
void test_usb_mux_chipset_reset(void)
{
- setup_ztest_proxy_chipset_reset(0, 2, EC_SUCCESS);
/* After this hook chipset reset functions should be called */
hook_notify(HOOK_CHIPSET_RESET);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_chipset_reset, NUM_OF_PROXY);
}
/* Test host command get mux info */
@@ -596,13 +722,9 @@ static void test_usb_mux_hc_mux_info(void)
struct ec_response_usb_pd_mux_info response;
struct ec_params_usb_pd_mux_info params;
struct host_cmd_handler_args args =
- BUILD_HOST_COMMAND(EC_CMD_USB_PD_MUX_INFO, 0, response);
+ BUILD_HOST_COMMAND(EC_CMD_USB_PD_MUX_INFO, 0, response, params);
mux_state_t exp_mode;
- /* Set up host command parameters */
- args.params = &params;
- args.params_size = sizeof(params);
-
/* Test invalid port parameter */
params.port = 5;
zassert_equal(EC_RES_INVALID_PARAM, host_command_process(&args), NULL);
@@ -611,27 +733,32 @@ static void test_usb_mux_hc_mux_info(void)
params.port = USBC_PORT_C1;
/* Test error on getting mux mode */
- setup_ztest_proxy_get(0, 0, EC_ERROR_UNKNOWN,
- USB_PD_MUX_TBT_COMPAT_ENABLED);
+ set_proxy_get_mux_state_seq(USB_PD_MUX_USB_ENABLED);
+ proxy_get_fake.return_val = EC_ERROR_UNKNOWN;
zassert_equal(EC_RES_ERROR, host_command_process(&args), NULL);
/* Test getting mux mode */
+ reset_proxy_fakes();
exp_mode = USB_PD_MUX_USB_ENABLED;
- setup_ztest_proxy_get(0, 2, EC_SUCCESS, exp_mode);
+ set_proxy_get_mux_state_seq(exp_mode);
zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
zassert_equal(args.response_size, sizeof(response), NULL);
zassert_equal(exp_mode, response.flags, "mode is 0x%x (!= 0x%x)",
response.flags, exp_mode);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_get, NUM_OF_PROXY);
/* Test clearing HPD IRQ */
+ reset_proxy_fakes();
exp_mode = USB_PD_MUX_USB_ENABLED | USB_PD_MUX_HPD_LVL |
USB_PD_MUX_HPD_IRQ;
- setup_ztest_proxy_get(0, 2, EC_SUCCESS, exp_mode);
- setup_ztest_proxy_hpd_update(0, 2, USB_PD_MUX_HPD_LVL);
+ set_proxy_get_mux_state_seq(exp_mode);
zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
zassert_equal(args.response_size, sizeof(response), NULL);
zassert_equal(exp_mode, response.flags, "mode is 0x%x (!= 0x%x)",
response.flags, exp_mode);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_get, NUM_OF_PROXY);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_hpd_update, NUM_OF_PROXY,
+ USB_PD_MUX_HPD_LVL);
}
/** Test typec console command */
@@ -667,96 +794,102 @@ static void test_usb_mux_typec_command(void)
* Test success on correct port number. Command should print mux state
* on console, but it is not possible to check that in unit test.
*/
- setup_ztest_proxy_get(0, 2, EC_SUCCESS, USB_PD_MUX_TBT_COMPAT_ENABLED);
+ set_proxy_get_mux_state_seq(USB_PD_MUX_TBT_COMPAT_ENABLED);
zassert_equal(EC_SUCCESS,
shell_execute_cmd(shell_backend_uart_get_ptr(),
"typec 1"), NULL);
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_get, NUM_OF_PROXY);
/* Test setting none mode */
+ reset_proxy_fakes();
exp_mode = USB_PD_MUX_NONE;
- setup_ztest_proxy_set(0, 2, EC_SUCCESS, exp_mode);
- /* Mux will enter low power mode */
- setup_ztest_proxy_enter_lpm(0, 2, EC_SUCCESS);
zassert_equal(EC_SUCCESS,
shell_execute_cmd(shell_backend_uart_get_ptr(),
"typec 1 none"), NULL);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_set, NUM_OF_PROXY, exp_mode);
+ /* Mux will enter low power mode */
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_enter_low_power_mode, NUM_OF_PROXY);
/* Test setting USB mode */
+ reset_proxy_fakes();
exp_mode = USB_PD_MUX_USB_ENABLED;
- setup_ztest_proxy_set(0, 2, EC_SUCCESS, exp_mode);
- /* Mux will exit low power mode */
- setup_ztest_proxy_init(0, 2, EC_SUCCESS);
zassert_equal(EC_SUCCESS,
shell_execute_cmd(shell_backend_uart_get_ptr(),
"typec 1 usb"), NULL);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_set, NUM_OF_PROXY, exp_mode);
+ /* Mux will exit low power mode */
+ CHECK_PROXY_FAKE_CALL_CNT(proxy_init, NUM_OF_PROXY);
/* Test setting DP mode */
+ reset_proxy_fakes();
exp_mode = USB_PD_MUX_DP_ENABLED;
- setup_ztest_proxy_set(0, 2, EC_SUCCESS, exp_mode);
zassert_equal(EC_SUCCESS,
shell_execute_cmd(shell_backend_uart_get_ptr(),
"typec 1 dp"), NULL);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_set, NUM_OF_PROXY, exp_mode);
/* Test setting dock mode */
+ reset_proxy_fakes();
exp_mode = USB_PD_MUX_USB_ENABLED | USB_PD_MUX_DP_ENABLED;
- setup_ztest_proxy_set(0, 2, EC_SUCCESS, exp_mode);
zassert_equal(EC_SUCCESS,
shell_execute_cmd(shell_backend_uart_get_ptr(),
"typec 1 dock"), NULL);
+ CHECK_PROXY_FAKE_CALL_CNT_MUX_STATE(proxy_set, NUM_OF_PROXY, exp_mode);
}
/** Setup proxy chain and uninit usb muxes */
void setup_uninit_mux(void)
{
- suspend_usbc_task(/*suspend=*/ true);
setup_usb_mux_proxy_chain();
+ set_test_runner_tid();
/* Makes sure that usb muxes of port 1 are not init */
usb_muxes[USBC_PORT_C1].flags = USB_MUX_FLAG_RESETS_IN_G3;
hook_notify(HOOK_CHIPSET_HARD_OFF);
+ reset_proxy_fakes();
}
/** Setup proxy chain and init usb muxes */
void setup_init_mux(void)
{
- suspend_usbc_task(/*suspend=*/ true);
setup_usb_mux_proxy_chain();
+ set_test_runner_tid();
/* Makes sure that usb muxes of port 1 are init */
- setup_ztest_proxy_init(0, 2, EC_SUCCESS);
usb_mux_init(USBC_PORT_C1);
+ reset_proxy_fakes();
}
void test_suite_usb_mux(void)
{
ztest_test_suite(usb_mux,
ztest_unit_test_setup_teardown(test_usb_mux_init,
- setup_uninit_mux, resotre_usb_mux_chain),
+ setup_uninit_mux, restore_usb_mux_chain),
ztest_unit_test_setup_teardown(test_usb_mux_set,
- setup_uninit_mux, resotre_usb_mux_chain),
+ setup_uninit_mux, restore_usb_mux_chain),
ztest_unit_test_setup_teardown(
test_usb_mux_reset_in_g3,
- setup_uninit_mux, resotre_usb_mux_chain),
+ setup_uninit_mux, restore_usb_mux_chain),
ztest_unit_test_setup_teardown(test_usb_mux_get,
- setup_uninit_mux, resotre_usb_mux_chain),
+ setup_uninit_mux, restore_usb_mux_chain),
ztest_unit_test_setup_teardown(
test_usb_mux_low_power_mode,
- setup_init_mux, resotre_usb_mux_chain),
+ setup_init_mux, restore_usb_mux_chain),
ztest_unit_test_setup_teardown(test_usb_mux_flip,
- setup_uninit_mux, resotre_usb_mux_chain),
+ setup_uninit_mux, restore_usb_mux_chain),
ztest_unit_test_setup_teardown(test_usb_mux_hpd_update,
- setup_uninit_mux, resotre_usb_mux_chain),
+ setup_uninit_mux, restore_usb_mux_chain),
ztest_unit_test_setup_teardown(
test_usb_mux_fw_update_port_info,
- setup_init_mux, resotre_usb_mux_chain),
+ setup_init_mux, restore_usb_mux_chain),
ztest_unit_test_setup_teardown(
test_usb_mux_chipset_reset,
- setup_init_mux, resotre_usb_mux_chain),
+ setup_init_mux, restore_usb_mux_chain),
ztest_unit_test_setup_teardown(
test_usb_mux_hc_mux_info,
- setup_init_mux, resotre_usb_mux_chain),
+ setup_init_mux, restore_usb_mux_chain),
ztest_unit_test_setup_teardown(
test_usb_mux_typec_command,
- setup_init_mux, resotre_usb_mux_chain));
+ setup_init_mux, restore_usb_mux_chain));
ztest_run_test_suite(usb_mux);
}