diff options
author | Boris Mittelberg <bmbm@google.com> | 2022-04-13 13:14:06 -0700 |
---|---|---|
committer | Boris Mittelberg <bmbm@google.com> | 2022-04-13 13:14:06 -0700 |
commit | 59ede6b1714c313de3e003c0497c70725bf625d5 (patch) | |
tree | cd524275223d5a5681888a5d1692bff2db688f3f | |
parent | 10cb14ae7b35f4ad9eb37f58ba3c48d20649e35b (diff) | |
parent | fb9f61782d452b106b9d9c4325fd473dcb4a7d8c (diff) | |
download | chrome-ec-59ede6b1714c313de3e003c0497c70725bf625d5.tar.gz |
Merge remote-tracking branch cros/main into firmware-brya-14505.B-main
Generated by: util/update_release_branch.py --baseboard brya
--relevant_paths_file baseboard/brya/relevant-paths.txt
firmware-brya-14505.B-main
Relevant changes:
git log --oneline 10cb14ae7..fb9f61782 -- baseboard/brya board/agah
board/anahera board/banshee board/brya board/crota board/felwinter
board/gimble board/kano board/primus board/redrix board/taeko
board/taniks board/vell board/volmar driver/bc12/pi3usb9201_public.*
driver/charger/bq25710.* driver/ppc/nx20p348x.*
driver/ppc/syv682x_public.* driver/retimer/bb_retimer_public.*
driver/tcpm/nct38xx.* driver/tcpm/ps8xxx_public.* driver/tcpm/tcpci.*
include/power/alderlake* include/intel_x86.h power/alderlake*
power/intel_x86.c util/getversion.sh
e4309526a Taniks: Support keyboard backlight control
c0333e1cb vell: Fix C3 TCPPC i2c address
61e177e69 anahera: Update fan table version 6-4
302a665c8 anahera: Update thermal high/halt point version 6-4
70016156d kano: Update keyboard backlight pwm frequency
82b4173c6 vell: Raise usbc ports i2c speed to 1Mhz
fd753e96c tarlo: undef configuration for clamshell device
3e3ef8f7a vell: Update thermal high/halt point version 3
76f3e5ad3 vell: Update fan table version 3
73502f93b taniks: add RGB mapping table
BRANCH=None
BUG=b:216026302 b:227522597 b:228410337 b:228525798 b:226215987
BUG=b:222125478 b:199246802 b:220196847 b:229039902
TEST=`make -j buildall`
Signed-off-by: Boris Mittelberg <bmbm@google.com>
Change-Id: Idfb129023ae067f927a89e2abc67c2286f17fd19
176 files changed, 3052 insertions, 1029 deletions
diff --git a/CPPLINT.cfg b/CPPLINT.cfg new file mode 100644 index 0000000000..d260909910 --- /dev/null +++ b/CPPLINT.cfg @@ -0,0 +1,4 @@ +set noparent +# Disable cpplint, since EC is a C project that follows Linux kernel style. +# cpplint is called by "cros lint". +exclude_files=.* diff --git a/PRESUBMIT.cfg b/PRESUBMIT.cfg index c726f14214..eac83bb0c5 100644 --- a/PRESUBMIT.cfg +++ b/PRESUBMIT.cfg @@ -23,6 +23,7 @@ cros_license_check : --exclude_regex=^third_party/unacl-curve25519/ [Hook Scripts] +cros lint = cros lint ${PRESUBMIT_FILES} presubmit_check = util/presubmit_check.sh config_option_check = util/config_option_check.py host_command_check = util/host_command_check.sh diff --git a/board/anahera/sensors.c b/board/anahera/sensors.c index 1ebfa7b97b..851930d1d3 100644 --- a/board/anahera/sensors.c +++ b/board/anahera/sensors.c @@ -77,11 +77,11 @@ BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); #define THERMAL_FAN \ { \ .temp_host = { \ - [EC_TEMP_THRESH_HIGH] = C_TO_K(73), \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ }, \ .temp_host_release = { \ - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(73), \ }, \ } __maybe_unused static const struct ec_thermal_config thermal_fan = THERMAL_FAN; @@ -128,8 +128,8 @@ __maybe_unused static const struct ec_thermal_config thermal_charger = #define THERMAL_REGULATOR \ { \ .temp_host = { \ - [EC_TEMP_THRESH_HIGH] = C_TO_K(53), \ - [EC_TEMP_THRESH_HALT] = C_TO_K(56), \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(55), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(60), \ }, \ .temp_host_release = { \ [EC_TEMP_THRESH_HIGH] = C_TO_K(48), \ diff --git a/board/anahera/thermal.c b/board/anahera/thermal.c index 8d9059bd09..8bd670c22a 100644 --- a/board/anahera/thermal.c +++ b/board/anahera/thermal.c @@ -37,38 +37,38 @@ struct fan_step { static const struct fan_step fan_table[] = { { /* level 0 */ - .on = {53, 54, 0, -1}, + .on = {53, 51, 0, -1}, .off = {99, 99, 99, -1}, .rpm = {0}, }, { /* level 1 */ - .on = {54, 55, 0, -1}, - .off = {52, 53, 99, -1}, + .on = {54, 52, 0, -1}, + .off = {52, 50, 99, -1}, .rpm = {3000}, }, { /* level 2 */ - .on = {55, 56, 0, -1}, - .off = {53, 54, 99, -1}, + .on = {55, 53, 0, -1}, + .off = {53, 51, 99, -1}, .rpm = {3400}, }, { /* level 3 */ - .on = {56, 57, 0, -1}, - .off = {54, 55, 99, -1}, + .on = {56, 54, 0, -1}, + .off = {54, 52, 99, -1}, .rpm = {3800}, }, { /* level 4 */ - .on = {57, 59, 54, -1}, - .off = {55, 56, 51, -1}, + .on = {57, 55, 54, -1}, + .off = {55, 53, 51, -1}, .rpm = {4100}, }, { /* level 5 */ - .on = {58, 60, 60, -1}, - .off = {56, 58, 52, -1}, + .on = {58, 56, 60, -1}, + .off = {56, 54, 52, -1}, .rpm = {4400}, }, { diff --git a/board/kano/pwm.c b/board/kano/pwm.c index dc09a2bed5..f2c0d0db7d 100644 --- a/board/kano/pwm.c +++ b/board/kano/pwm.c @@ -20,7 +20,7 @@ const struct pwm_t pwm_channels[] = { * lower PWM frequencies, but higher frequencies record a much * lower maximum power. */ - .freq = 2400, + .freq = 25000, }, [PWM_CH_FAN] = { .channel = 5, diff --git a/board/quackingstick/board.c b/board/quackingstick/board.c index 8806e8c845..48414a2d0c 100644 --- a/board/quackingstick/board.c +++ b/board/quackingstick/board.c @@ -20,6 +20,7 @@ #include "driver/tcpm/tcpci.h" #include "gpio.h" #include "hooks.h" +#include "led_common.h" #include "lid_switch.h" #include "mkbp_input_devices.h" #include "peripheral_charger.h" @@ -450,6 +451,13 @@ DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C+1); void board_hibernate(void) { int i; + uint8_t brightness_range[EC_LED_COLOR_COUNT] = { 0 }; + + /* + * Turn off LED. + */ + led_set_brightness(EC_LED_ID_BATTERY_LED, brightness_range); + led_auto_control(EC_LED_ID_BATTERY_LED, 0); /* * Sensors are unpowered in hibernate. Apply PD to the diff --git a/board/scout/board.c b/board/scout/board.c index 6e2b2d1e4e..ce0ee8ceae 100644 --- a/board/scout/board.c +++ b/board/scout/board.c @@ -98,7 +98,7 @@ static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { struct motion_sensor_t motion_sensors[] = { [CLEAR_ALS] = { .name = "Clear Light", - .active_mask = SENSOR_ACTIVE_S0_S3, + .active_mask = SENSOR_ACTIVE_S0, .chip = MOTIONSENSE_CHIP_TCS3400, .type = MOTIONSENSE_TYPE_LIGHT, .location = MOTIONSENSE_LOC_BASE, @@ -119,7 +119,7 @@ struct motion_sensor_t motion_sensors[] = { }, [RGB_ALS] = { .name = "RGB Light", - .active_mask = SENSOR_ACTIVE_S0_S3, + .active_mask = SENSOR_ACTIVE_S0, .chip = MOTIONSENSE_CHIP_TCS3400, .type = MOTIONSENSE_TYPE_LIGHT_RGB, .location = MOTIONSENSE_LOC_BASE, diff --git a/board/scout/board.h b/board/scout/board.h index 67b9c3bdeb..6985742439 100644 --- a/board/scout/board.h +++ b/board/scout/board.h @@ -50,6 +50,8 @@ #define CONFIG_SHA256 /* Sensor */ +#undef CONFIG_MOTION_SENSE_RESUME_DELAY_US +#define CONFIG_MOTION_SENSE_RESUME_DELAY_US (1000 * MSEC) #define CONFIG_ACCEL_INTERRUPTS #define CONFIG_CMD_ACCEL_INFO /* Enable sensor fifo, must also define the _SIZE and _THRES */ diff --git a/board/taeko/board.h b/board/taeko/board.h index 406749f8b8..77dbdbe637 100644 --- a/board/taeko/board.h +++ b/board/taeko/board.h @@ -152,6 +152,7 @@ /* System has back-lit keyboard */ #define CONFIG_PWM_KBLIGHT +#undef CONFIG_MKBP_INPUT_DEVICES /* I2C Bus Configuration */ #define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 diff --git a/board/taniks/board.h b/board/taniks/board.h index b9016cdbbb..07780d90f2 100644 --- a/board/taniks/board.h +++ b/board/taniks/board.h @@ -179,7 +179,8 @@ #define GPIO_WP_L GPIO_EC_WP_ODL /* System has back-lit keyboard */ -#define CONFIG_PWM_KBLIGHT +#define CONFIG_PWM +#define CONFIG_KEYBOARD_BACKLIGHT /* I2C Bus Configuration */ #define I2C_PORT_SENSOR NPCX_I2C_PORT0_0 @@ -294,7 +295,6 @@ enum battery_type { }; enum pwm_channel { - PWM_CH_KBLIGHT = 0, /* PWM3 */ PWM_CH_FAN, /* PWM5 */ PWM_CH_COUNT }; diff --git a/board/taniks/keyboard.c b/board/taniks/keyboard.c index 963453d3e6..e906275d1b 100644 --- a/board/taniks/keyboard.c +++ b/board/taniks/keyboard.c @@ -68,6 +68,47 @@ const uint8_t rgbkbd_vsize = RGB_GRID0_ROW; const uint8_t rgbkbd_map[] = { RGBKBD_DELM, + RGBKBD_COORD( 0, 0), RGBKBD_DELM, + RGBKBD_COORD( 1, 0), RGBKBD_DELM, + RGBKBD_COORD( 2, 0), RGBKBD_DELM, + RGBKBD_COORD( 3, 0), RGBKBD_DELM, + RGBKBD_COORD( 4, 0), RGBKBD_DELM, + RGBKBD_COORD( 5, 0), RGBKBD_DELM, + RGBKBD_COORD( 6, 0), RGBKBD_DELM, + RGBKBD_COORD( 7, 0), RGBKBD_DELM, + RGBKBD_COORD( 0, 1), RGBKBD_DELM, + RGBKBD_COORD( 1, 1), RGBKBD_DELM, + RGBKBD_COORD( 2, 1), RGBKBD_DELM, + RGBKBD_COORD( 3, 1), RGBKBD_DELM, + RGBKBD_COORD( 4, 1), RGBKBD_DELM, + RGBKBD_COORD( 5, 1), RGBKBD_DELM, + RGBKBD_COORD( 6, 1), RGBKBD_DELM, + RGBKBD_COORD( 7, 1), RGBKBD_DELM, + RGBKBD_COORD( 0, 2), RGBKBD_DELM, + RGBKBD_COORD( 1, 2), RGBKBD_DELM, + RGBKBD_COORD( 2, 2), RGBKBD_DELM, + RGBKBD_COORD( 3, 2), RGBKBD_DELM, + RGBKBD_COORD( 4, 2), RGBKBD_DELM, + RGBKBD_COORD( 5, 2), RGBKBD_DELM, + RGBKBD_COORD( 6, 2), RGBKBD_DELM, + RGBKBD_COORD( 7, 2), RGBKBD_DELM, + RGBKBD_COORD( 0, 3), RGBKBD_DELM, + RGBKBD_COORD( 1, 3), RGBKBD_DELM, + RGBKBD_COORD( 2, 3), RGBKBD_DELM, + RGBKBD_COORD( 3, 3), RGBKBD_DELM, + RGBKBD_COORD( 4, 3), RGBKBD_DELM, + RGBKBD_COORD( 5, 3), RGBKBD_DELM, + RGBKBD_COORD( 6, 3), RGBKBD_DELM, + RGBKBD_COORD( 7, 3), RGBKBD_DELM, + RGBKBD_COORD( 0, 4), RGBKBD_DELM, + RGBKBD_COORD( 1, 4), RGBKBD_DELM, + RGBKBD_COORD( 2, 4), RGBKBD_DELM, + RGBKBD_COORD( 3, 4), RGBKBD_DELM, + RGBKBD_COORD( 4, 4), RGBKBD_DELM, + RGBKBD_COORD( 5, 4), RGBKBD_DELM, + RGBKBD_COORD( 6, 4), RGBKBD_DELM, + RGBKBD_COORD( 7, 4), RGBKBD_DELM, + RGBKBD_DELM, }; const size_t rgbkbd_map_size = ARRAY_SIZE(rgbkbd_map); diff --git a/board/taniks/pwm.c b/board/taniks/pwm.c index b5fef384f9..7e834385bf 100644 --- a/board/taniks/pwm.c +++ b/board/taniks/pwm.c @@ -11,17 +11,6 @@ #include "pwm_chip.h" const struct pwm_t pwm_channels[] = { - [PWM_CH_KBLIGHT] = { - .channel = 3, - .flags = 0, - /* - * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent - * flicker. Higher frequencies consume similar average power to - * lower PWM frequencies, but higher frequencies record a much - * lower maximum power. - */ - .freq = 2400, - }, [PWM_CH_FAN] = { .channel = 5, .flags = PWM_CONFIG_OPEN_DRAIN, @@ -29,11 +18,3 @@ const struct pwm_t pwm_channels[] = { }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); - -static void board_pwm_init(void) -{ - - pwm_enable(PWM_CH_KBLIGHT, 1); - pwm_set_duty(PWM_CH_KBLIGHT, 50); -} -DECLARE_HOOK(HOOK_INIT, board_pwm_init, HOOK_PRIO_DEFAULT); diff --git a/board/vell/i2c.c b/board/vell/i2c.c index def6bff688..4f505d74c7 100644 --- a/board/vell/i2c.c +++ b/board/vell/i2c.c @@ -22,7 +22,7 @@ const struct i2c_port_t i2c_ports[] = { /* I2C1 */ .name = "tcpc0,1", .port = I2C_PORT_USB_C0_C1_TCPC, - .kbps = 400, + .kbps = 1000, .scl = GPIO_EC_I2C_USB_C0_C1_TCPC_SCL, .sda = GPIO_EC_I2C_USB_C0_C1_TCPC_SDA, }, @@ -30,7 +30,7 @@ const struct i2c_port_t i2c_ports[] = { /* I2C2 */ .name = "ppc0,1", .port = I2C_PORT_USB_C0_C1_PPC, - .kbps = 400, + .kbps = 1000, .scl = GPIO_EC_I2C_USB_C0_C1_PPC_BC_SCL, .sda = GPIO_EC_I2C_USB_C0_C1_PPC_BC_SDA, }, @@ -38,7 +38,7 @@ const struct i2c_port_t i2c_ports[] = { /* I2C3 */ .name = "retimer0,1,2,3", .port = I2C_PORT_USB_C0_C1_MUX, - .kbps = 400, + .kbps = 1000, .scl = GPIO_EC_I2C_USB_RT_SCL, .sda = GPIO_EC_I2C_USB_RT_SDA, }, @@ -46,7 +46,7 @@ const struct i2c_port_t i2c_ports[] = { /* I2C4 */ .name = "tcpc2,3", .port = I2C_PORT_USB_C2_C3_TCPC, - .kbps = 400, + .kbps = 1000, .scl = GPIO_EC_I2C_USB_C2_C3_TCPC_SCL, .sda = GPIO_EC_I2C_USB_C2_C3_TCPC_SDA, }, @@ -62,7 +62,7 @@ const struct i2c_port_t i2c_ports[] = { /* I2C6 */ .name = "ppc2,3", .port = I2C_PORT_USB_C2_C3_PPC, - .kbps = 400, + .kbps = 1000, .scl = GPIO_EC_I2C_USB_C2_C3_PPC_BC_RT_SCL, .sda = GPIO_EC_I2C_USB_C2_C3_PPC_BC_RT_SDA, }, diff --git a/board/vell/sensors.c b/board/vell/sensors.c index aad7fc4ae4..3a4ceb2dc9 100644 --- a/board/vell/sensors.c +++ b/board/vell/sensors.c @@ -211,10 +211,10 @@ BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); { \ .temp_host = { \ [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ - [EC_TEMP_THRESH_HALT] = C_TO_K(90), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(95), \ }, \ .temp_host_release = { \ - [EC_TEMP_THRESH_HIGH] = C_TO_K(80), \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ }, \ } __maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; @@ -228,11 +228,11 @@ __maybe_unused static const struct ec_thermal_config thermal_cpu = THERMAL_CPU; #define THERMAL_CHARGER \ { \ .temp_host = { \ - [EC_TEMP_THRESH_HIGH] = C_TO_K(70), \ - [EC_TEMP_THRESH_HALT] = C_TO_K(80), \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(85), \ + [EC_TEMP_THRESH_HALT] = C_TO_K(95), \ }, \ .temp_host_release = { \ - [EC_TEMP_THRESH_HIGH] = C_TO_K(65), \ + [EC_TEMP_THRESH_HIGH] = C_TO_K(90), \ }, \ } __maybe_unused static const struct ec_thermal_config thermal_charger = diff --git a/board/vell/thermal.c b/board/vell/thermal.c index 00b3e2ae9a..e72b86e3b1 100644 --- a/board/vell/thermal.c +++ b/board/vell/thermal.c @@ -19,13 +19,13 @@ struct fan_step { /* - * Sensor 1~4 trigger point, set -1 if we're not using this + * Sensor 1~5 trigger point, set -1 if we're not using this * sensor to determine fan speed. */ int8_t on[TEMP_SENSOR_COUNT]; /* - * Sensor 1~4 trigger point, set -1 if we're not using this + * Sensor 1~5 trigger point, set -1 if we're not using this * sensor to determine fan speed. */ int8_t off[TEMP_SENSOR_COUNT]; @@ -37,32 +37,26 @@ struct fan_step { static const struct fan_step fan_table[] = { { /* level 0 */ - .on = {49, 60, -1, 50, -1}, - .off = {99, 99, -1, 99, -1}, + .on = {48, 60, 48, 47, -1}, + .off = {99, 99, 99, 99, -1}, .rpm = {0}, }, { /* level 1 */ - .on = {50, 60, -1, 51, -1}, - .off = {48, 99, -1, 49, -1}, - .rpm = {3400}, + .on = {50, 60, 50, 49, -1}, + .off = {47, 99, 47, 46, -1}, + .rpm = {3600}, }, { /* level 2 */ - .on = {52, 60, -1, 53, -1}, - .off = {49, 99, -1, 50, -1}, - .rpm = {4000}, + .on = {53, 60, 53, 52, -1}, + .off = {49, 99, 49, 48, -1}, + .rpm = {4100}, }, { /* level 3 */ - .on = {54, 64, -1, 55, -1}, - .off = {51, 59, -1, 52, -1}, - .rpm = {4450}, - }, - { - /* level 4 */ - .on = {100, 100, -1, 100, -1}, - .off = {53, 63, -1, 54, -1}, + .on = {100, 100, 100, 100, -1}, + .off = {51, 59, 51, 50, -1}, .rpm = {5500}, }, }; @@ -84,14 +78,17 @@ static int fan_table_to_rpm(int fan, int *temp) */ if (temp[TEMP_SENSOR_1_SOC] < prev_tmp[TEMP_SENSOR_1_SOC] || temp[TEMP_SENSOR_2_CHARGER] < prev_tmp[TEMP_SENSOR_2_CHARGER] || + temp[TEMP_SENSOR_3_WWAN] < prev_tmp[TEMP_SENSOR_3_WWAN] || temp[TEMP_SENSOR_4_DDR] < prev_tmp[TEMP_SENSOR_4_DDR]) { for (i = current_level; i > 0; i--) { if (temp[TEMP_SENSOR_1_SOC] < fan_table[i].off[TEMP_SENSOR_1_SOC] && - temp[TEMP_SENSOR_4_DDR] < - fan_table[i].off[TEMP_SENSOR_4_DDR] && temp[TEMP_SENSOR_2_CHARGER] < - fan_table[i].off[TEMP_SENSOR_2_CHARGER]) + fan_table[i].off[TEMP_SENSOR_2_CHARGER] && + temp[TEMP_SENSOR_3_WWAN] < + fan_table[i].off[TEMP_SENSOR_3_WWAN] && + temp[TEMP_SENSOR_4_DDR] < + fan_table[i].off[TEMP_SENSOR_4_DDR]) current_level = i - 1; else break; @@ -99,15 +96,19 @@ static int fan_table_to_rpm(int fan, int *temp) } else if (temp[TEMP_SENSOR_1_SOC] > prev_tmp[TEMP_SENSOR_1_SOC] || temp[TEMP_SENSOR_2_CHARGER] > prev_tmp[TEMP_SENSOR_2_CHARGER] || + temp[TEMP_SENSOR_3_WWAN] > + prev_tmp[TEMP_SENSOR_3_WWAN] || temp[TEMP_SENSOR_4_DDR] > prev_tmp[TEMP_SENSOR_4_DDR]) { for (i = current_level; i < NUM_FAN_LEVELS; i++) { if (temp[TEMP_SENSOR_1_SOC] > fan_table[i].on[TEMP_SENSOR_1_SOC] || + (temp[TEMP_SENSOR_2_CHARGER] > + fan_table[i].on[TEMP_SENSOR_2_CHARGER] && + temp[TEMP_SENSOR_3_WWAN] > + fan_table[i].on[TEMP_SENSOR_3_WWAN]) || temp[TEMP_SENSOR_4_DDR] > - fan_table[i].on[TEMP_SENSOR_4_DDR] || - temp[TEMP_SENSOR_2_CHARGER] > - fan_table[i].on[TEMP_SENSOR_2_CHARGER]) + fan_table[i].on[TEMP_SENSOR_4_DDR]) current_level = i + 1; else break; diff --git a/board/vell/usbc_config.c b/board/vell/usbc_config.c index ee61614361..3831b13884 100644 --- a/board/vell/usbc_config.c +++ b/board/vell/usbc_config.c @@ -99,7 +99,7 @@ struct ppc_config_t ppc_chips[] = { }, [USBC_PORT_C3] = { .i2c_port = I2C_PORT_USB_C2_C3_PPC, - .i2c_addr_flags = SYV682X_ADDR3_FLAGS, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, .drv = &syv682x_drv, }, }; @@ -107,6 +107,12 @@ BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); +struct ppc_config_t ppc_chips_old_c3 = { + .i2c_port = I2C_PORT_USB_C2_C3_PPC, + .i2c_addr_flags = SYV682X_ADDR3_FLAGS, + .drv = &syv682x_drv, +}; + /* USBC mux configuration - Alder Lake includes internal mux */ static const struct usb_mux usbc0_tcss_usb_mux = { .usb_port = USBC_PORT_C0, @@ -336,6 +342,9 @@ static void board_tcpc_init(void) for (i = 0; i < CONFIG_IO_EXPANDER_PORT_COUNT; ++i) ioex_init(i); + if (get_board_id() < 2) + ppc_chips[USBC_PORT_C3] = ppc_chips_old_c3; + /* Enable PPC interrupts. */ gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); diff --git a/common/keyboard_backlight.c b/common/keyboard_backlight.c index 24a8ae56dd..4940d9a97e 100644 --- a/common/keyboard_backlight.c +++ b/common/keyboard_backlight.c @@ -10,6 +10,7 @@ #include "host_command.h" #include "keyboard_backlight.h" #include "lid_switch.h" +#include "rgb_keyboard.h" #include "timer.h" #include "util.h" @@ -90,9 +91,11 @@ int kblight_register(const struct kblight_drv *drv) static void keyboard_backlight_init(void) { /* Uses PWM by default. Can be customized by board_kblight_init */ -#ifdef CONFIG_PWM_KBLIGHT - kblight_register(&kblight_pwm); -#endif + if (IS_ENABLED(CONFIG_PWM_KBLIGHT)) + kblight_register(&kblight_pwm); + else if (IS_ENABLED(CONFIG_RGB_KEYBOARD)) + kblight_register(&kblight_rgbkbd); + board_kblight_init(); if (kblight_init()) CPRINTS("kblight init failed"); diff --git a/common/motion_sense.c b/common/motion_sense.c index 46972de886..41e52cd10b 100644 --- a/common/motion_sense.c +++ b/common/motion_sense.c @@ -1154,7 +1154,7 @@ static enum ec_status host_cmd_motion_sense(struct host_cmd_handler_args *args) case MOTIONSENSE_CMD_EC_RATE: sensor = host_sensor_id_to_real_sensor( - in->sensor_odr.sensor_num); + in->ec_rate.sensor_num); if (sensor == NULL) return EC_RES_INVALID_PARAM; diff --git a/common/pwm.c b/common/pwm.c index 74c079bbfd..7699405f3d 100644 --- a/common/pwm.c +++ b/common/pwm.c @@ -9,6 +9,7 @@ #include "hooks.h" #include "host_command.h" #include "pwm.h" +#include "rgb_keyboard.h" #include "util.h" #ifdef CONFIG_PWM @@ -64,11 +65,18 @@ host_command_pwm_set_duty(struct host_cmd_handler_args *args) const struct ec_params_pwm_set_duty *p = args->params; enum pwm_channel channel; - if (get_target_channel(&channel, p->pwm_type, p->index)) - return EC_RES_INVALID_PARAM; - - pwm_set_raw_duty(channel, p->duty); - pwm_enable(channel, p->duty > 0); + if (IS_ENABLED(CONFIG_RGB_KEYBOARD) && + (p->pwm_type == EC_PWM_TYPE_KB_LIGHT)) { + uint8_t gcc = DIV_ROUND_NEAREST(p->duty * RGBKBD_MAX_GCC_LEVEL, + EC_PWM_MAX_DUTY); + if (rgbkbd_set_global_brightness(gcc)) + return EC_RES_ERROR; + } else { + if (get_target_channel(&channel, p->pwm_type, p->index)) + return EC_RES_INVALID_PARAM; + pwm_set_raw_duty(channel, p->duty); + pwm_enable(channel, p->duty > 0); + } return EC_RES_SUCCESS; } @@ -82,12 +90,23 @@ host_command_pwm_get_duty(struct host_cmd_handler_args *args) const struct ec_params_pwm_get_duty *p = args->params; struct ec_response_pwm_get_duty *r = args->response; - enum pwm_channel channel; + if (IS_ENABLED(CONFIG_RGB_KEYBOARD) && + (p->pwm_type == EC_PWM_TYPE_KB_LIGHT)) { + uint8_t gcc; - if (get_target_channel(&channel, p->pwm_type, p->index)) - return EC_RES_INVALID_PARAM; + if (rgbkbd_get_global_brightness(&gcc)) + return EC_RES_ERROR; + r->duty = DIV_ROUND_NEAREST(gcc * EC_PWM_MAX_DUTY, + RGBKBD_MAX_GCC_LEVEL); + } else { + enum pwm_channel channel; + + if (get_target_channel(&channel, p->pwm_type, p->index)) + return EC_RES_INVALID_PARAM; + + r->duty = pwm_get_raw_duty(channel); + } - r->duty = pwm_get_raw_duty(channel); args->response_size = sizeof(*r); return EC_RES_SUCCESS; diff --git a/common/rgb_keyboard.c b/common/rgb_keyboard.c index 4edbcac3a8..c9987c5e5b 100644 --- a/common/rgb_keyboard.c +++ b/common/rgb_keyboard.c @@ -11,6 +11,7 @@ #include "gpio.h" #include "hooks.h" #include "host_command.h" +#include "keyboard_backlight.h" #include "registers.h" #include "rgb_keyboard.h" #include "task.h" @@ -38,16 +39,17 @@ uint8_t rgbkbd_table[EC_RGBKBD_MAX_KEY_COUNT]; static int set_color_single(struct rgb_s color, int x, int y) { struct rgbkbd *ctx = &rgbkbds[0]; - uint8_t gid; + uint8_t grid; uint8_t col = 0; uint8_t offset; + int rv; if (rgbkbd_hsize <= x || rgbkbd_vsize <= y) { return EC_ERROR_OVERFLOW; } /* Search the grid where x belongs to. */ - for (gid = 0; gid < rgbkbd_count; gid++, ctx++) { + for (grid = 0; grid < rgbkbd_count; grid++, ctx++) { if (x < col + ctx->cfg->col_len) break; col += ctx->cfg->col_len; @@ -56,9 +58,13 @@ static int set_color_single(struct rgb_s color, int x, int y) offset = ctx->cfg->row_len * (x - col) + y; ctx->buf[offset] = color; - CPRINTS("Set [%d,%d] to color=[%d,%d,%d] (gid=%u offset=%u)", - x, y, color.r, color.g, color.b, gid, offset); - return ctx->cfg->drv->set_color(ctx, offset, &ctx->buf[offset], 1); + rv = ctx->cfg->drv->set_color(ctx, offset, &ctx->buf[offset], 1); + + CPRINTS("%set (%d,%d) to color=(%d,%d,%d) grid=%u offset=%u (%d)", + rv ? "Failed to s" : "S", + x, y, color.r, color.g, color.b, grid, offset, rv); + + return rv; } test_export_static uint8_t get_grid_size(const struct rgbkbd *ctx) @@ -228,29 +234,154 @@ void rgbkbd_init_lookup_table(void) */ } +int rgbkbd_set_global_brightness(uint8_t gcc) +{ + int e, grid; + int rv = EC_SUCCESS; + + for (grid = 0; grid < rgbkbd_count; grid++) { + struct rgbkbd *ctx = &rgbkbds[grid]; + + e = ctx->cfg->drv->set_gcc(ctx, gcc); + if (e) { + CPRINTS("Failed to set GCC to %u for grid=%d (%d)", + gcc, grid, e); + rv = e; + continue; + } + + ctx->gcc = gcc; + } + + CPRINTS("Set GCC to %u", gcc); + + /* Return EC_SUCCESS or the last error. */ + return rv; +} + +int rgbkbd_get_global_brightness(uint8_t *gcc) +{ + *gcc = rgbkbds[0].gcc; + + return EC_SUCCESS; +} + __overridable void board_enable_rgb_keyboard(bool enable) {} -void rgbkbd_task(void *u) +static int rgbkbd_init(void) { - uint32_t event; - int i, rv; + int rv = EC_SUCCESS; + int e, i; + bool updated = false; - board_enable_rgb_keyboard(true); + for (i = 0; i < rgbkbd_count; i++) { + struct rgbkbd *ctx = &rgbkbds[i]; - rgbkbd_init_lookup_table(); + if (ctx->state >= RGBKBD_STATE_INITIALIZED) + continue; + + e = ctx->cfg->drv->init(ctx); + if (e) { + CPRINTS("Failed to init GRID%d (%d)", i, e); + rv = e; + continue; + } + + ctx->state = RGBKBD_STATE_INITIALIZED; + updated = true; + + e = ctx->cfg->drv->set_scale(ctx, 0, 0x80, get_grid_size(ctx)); + if (e) { + CPRINTS("Failed to set scale of GRID%d (%d)", i, e); + rv = e; + } + } + + if (updated) + CPRINTS("Initialized (%d)", rv); + + /* Return EC_SUCCESS or the last error. */ + return rv; +} + +static int rgbkbd_enable(int enable) +{ + int rv = EC_SUCCESS; + int e, i; + bool updated = false; for (i = 0; i < rgbkbd_count; i++) { struct rgbkbd *ctx = &rgbkbds[i]; - rv = ctx->cfg->drv->init(ctx); - if (rv) - CPRINTS("Failed to init GRID%d (%d)", i, rv); - rv = ctx->cfg->drv->set_gcc(ctx, 0x80); - rv |= ctx->cfg->drv->set_scale(ctx, 0, 0x80, - get_grid_size(ctx)); - if (rv) - CPRINTS("Failed to set GCC or scale (%d)", rv); + + if (ctx->state >= RGBKBD_STATE_ENABLED && enable) + continue; + + e = ctx->cfg->drv->enable(ctx, enable); + if (e) { + CPRINTS("Failed to %s GRID%d (%d)", + enable ? "enable" : "disable", i, e); + rv = e; + continue; + } + + ctx->state = enable ? + RGBKBD_STATE_ENABLED : RGBKBD_STATE_DISABLED; + updated = true; } + if (updated) + CPRINTS("%s (%d)", enable ? "Enabled" : "Disabled", rv); + + /* Return EC_SUCCESS or the last error. */ + return rv; +} + +static int rgbkbd_kblight_set(int percent) +{ + uint8_t gcc = DIV_ROUND_NEAREST(percent * RGBKBD_MAX_GCC_LEVEL, 100); + return rgbkbd_set_global_brightness(gcc); +} + +static int rgbkbd_kblight_get(void) +{ + uint8_t gcc; + + if (rgbkbd_get_global_brightness(&gcc)) + return 0; + + return DIV_ROUND_NEAREST(gcc * 100, RGBKBD_MAX_GCC_LEVEL); +} + +static int rgbkbd_get_enabled(void) +{ + return rgbkbds[0].state >= RGBKBD_STATE_ENABLED; +} + +const struct kblight_drv kblight_rgbkbd = { + .init = rgbkbd_init, + .set = rgbkbd_kblight_set, + .get = rgbkbd_kblight_get, + /* + * We need to let RGBKBD manage enable/disable the backlight to keep + * the LEDs under the control of RGBKBD. Registering NULL also avoids + * ASSERT(!in_interrupt_context()) failure in task.c called from + * rgbkbd_enable API. + */ + .enable = NULL, + .get_enabled = rgbkbd_get_enabled, +}; + +void rgbkbd_task(void *u) +{ + uint32_t event; + + board_enable_rgb_keyboard(true); + + rgbkbd_init_lookup_table(); + rgbkbd_init(); + rgbkbd_enable(1); + rgbkbd_set_global_brightness(0x80); + while (1) { event = task_wait_event(100 * MSEC); if (IS_ENABLED(CONFIG_RGB_KEYBOARD_DEBUG)) @@ -310,7 +441,6 @@ DECLARE_HOST_COMMAND(EC_CMD_RGBKBD, hc_rgbkbd, EC_VER_MASK(0)); test_export_static int cc_rgbk(int argc, char **argv) { - struct rgbkbd *ctx; char *end, *comma; struct rgb_s color; int gcc, x, y, val; @@ -351,12 +481,7 @@ test_export_static int cc_rgbk(int argc, char **argv) gcc = strtoi(argv[1], &end, 0); if (*end || gcc < 0 || gcc > UINT8_MAX) return EC_ERROR_PARAM1; - demo = RGBKBD_DEMO_OFF; - for (i = 0; i < rgbkbd_count; i++) { - ctx = &rgbkbds[i]; - ctx->cfg->drv->set_gcc(ctx, gcc); - } - return EC_SUCCESS; + return rgbkbd_set_global_brightness(gcc); } if (argc != 5) diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c index aa7812bbed..defeebecfa 100644 --- a/common/usbc/usb_pe_drp_sm.c +++ b/common/usbc/usb_pe_drp_sm.c @@ -5020,14 +5020,18 @@ __maybe_unused static void pe_frs_snk_src_start_ams_entry(int port) print_current_state(port); - /* Contract is invalid now */ - pe_invalidate_explicit_contract(port); - /* Inform Protocol Layer this is start of AMS */ PE_SET_FLAG(port, PE_FLAGS_LOCALLY_INITIATED_AMS); /* Shared PRS/FRS code, indicate FRS path */ PE_SET_FLAG(port, PE_FLAGS_FAST_ROLE_SWAP_PATH); + + /* + * Invalidate the contract after the FRS flags set so the + * flags can be propagated to this function. + */ + pe_invalidate_explicit_contract(port); + set_state_pe(port, PE_PRS_SNK_SRC_SEND_SWAP); } diff --git a/core/cortex-m/irq_handler.h b/core/cortex-m/irq_handler.h index 89be593eee..dceda73958 100644 --- a/core/cortex-m/irq_handler.h +++ b/core/cortex-m/irq_handler.h @@ -9,9 +9,10 @@ #define __CROS_EC_IRQ_HANDLER_H #ifdef CONFIG_TASK_PROFILING -#define bl_task_start_irq_handler "bl task_start_irq_handler\n" +#define TASK_START_IRQ_HANDLER(excep_return) \ + task_start_irq_handler(excep_return) #else -#define bl_task_start_irq_handler "" +#define TASK_START_IRQ_HANDLER(excep_return) #endif /* Helper macros to build the IRQ handler and priority struct names */ @@ -23,20 +24,17 @@ */ #define DECLARE_IRQ(irq, routine, priority) DECLARE_IRQ_(irq, routine, priority) #define DECLARE_IRQ_(irq, routine, priority) \ - void IRQ_HANDLER(irq)(void) __attribute__((naked)); \ + void IRQ_HANDLER(irq)(void); \ typedef struct { \ int fake[irq >= CONFIG_IRQ_COUNT ? -1 : 1]; \ } irq_num_check_##irq; \ static void __keep routine(void); \ void IRQ_HANDLER(irq)(void) \ { \ - asm volatile("mov r0, lr\n" \ - "push {r0, lr}\n" \ - bl_task_start_irq_handler \ - "bl "#routine"\n" \ - "pop {r0, lr}\n" \ - "b task_resched_if_needed\n" \ - ); \ + void *ret = __builtin_return_address(0); \ + TASK_START_IRQ_HANDLER(ret); \ + routine(); \ + task_resched_if_needed(ret); \ } \ const struct irq_priority __keep IRQ_PRIORITY(irq) \ __attribute__((section(".rodata.irqprio"))) \ diff --git a/docs/ec_terms.md b/docs/ec_terms.md index d5f3690615..b865df0078 100644 --- a/docs/ec_terms.md +++ b/docs/ec_terms.md @@ -65,6 +65,11 @@ switching, sensor management, and other functions, offloading these tasks from the [AP](#ap). +* **ectool** {#ectool} + + The [ectool] is the [AP](#ap) console's CLI for sending commands to the + [EC](#ec). + * **EC-3PO** {#ec-3po} A replacement of the current UART-based console which moves much of the code @@ -232,17 +237,22 @@ second). Typical use is to provide a debug console to the EC. [RS-232] is the protocol standard used by UARTs. +* **USBA - USB Type-A** {#usba} + + Traditional USB Host port. + * **VCONN - Connector Voltage** {#vconn} See the [USB-C documentation](./usb-c.md#vconn) for more details. [BC 1.2 Specification]: <https://www.usb.org/document-library/battery-charging-v12-spec-and-adopters-agreement> -[CrOS Board Info]: <https://chromium.googlesource.com/chromiumos/docs/+/HEAD/design_docs/cros_board_info.md> [CEC Wikipedia page]: <https://en.wikipedia.org/wiki/Consumer_Electronics_Control> +[CrOS Board Info]: <https://chromium.googlesource.com/chromiumos/docs/+/HEAD/design_docs/cros_board_info.md> [DPTF Readme]: <https://github.com/intel/dptf/blob/HEAD/README.txt> -[eSPI Specification]: <https://www.intel.com/content/dam/support/us/en/documents/software/chipset-software/327432-004_espi_base_specification_rev1.0.pdf> +[EC MKBP driver]: <https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/common/keyboard_mkbp.c> [FAFT design doc]: <https://chromium.googlesource.com/chromiumos/third_party/autotest/+/HEAD/docs/faft-design-doc.md> [I2C Specification]: <https://www.nxp.com/docs/en/user-guide/UM10204.pdf> -[RS-232]: <https://en.wikipedia.org/wiki/RS-232> -[EC MKBP driver]: <https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/common/keyboard_mkbp.c> [Low Pin Count bus]: https://en.wikipedia.org/wiki/Low_Pin_Count +[RS-232]: <https://en.wikipedia.org/wiki/RS-232> +[eSPI Specification]: <https://www.intel.com/content/dam/support/us/en/documents/software/chipset-software/327432-004_espi_base_specification_rev1.0.pdf> +[ectool]: ../docs/ap-ec-comm.md diff --git a/docs/zephyr/zephyr_ap_power.md b/docs/zephyr/zephyr_ap_power.md new file mode 100644 index 0000000000..0b95e375d6 --- /dev/null +++ b/docs/zephyr/zephyr_ap_power.md @@ -0,0 +1,58 @@ +# Zephyr EC AP Power Requirements + +[TOC] + +## Overview + +[AP] power configures the minimum amount of power needed to boot the Application +Processor. + +## Kconfig Options + +The Kconfig option `CONFIG_PLATFORM_EC_BOOT_AP_POWER_REQUIREMENTS` enables checking power +thresholds before booting the AP. See the file [Kconfig.ap_power] for all Kconfig +options related to this feature. + +## Devicetree Nodes + +None required. + +## Board Specific Code + +None required. + +## Threads + +AP_POWER support does not enable any threads. + +## Testing and Debugging + +Use the battfake command to force the battery level, independent of the actual battery charge. +To verify the AP power thresholds, force the battery level below the +`CONFIG_PLATFORM_EC_CHARGER_MIN_BAT_PCT_FOR_POWER_ON` setting and reboot the EC. +The EC should prevent the AP from powering up. + +`battfake` usage: battfake <percent> (-1 = use real level) + +``` +battfake 2 +reboot +/* Verify that AP does ot boot */ +battfak3 3 +/* Verify that AP boots */ +/* Restore normal operation */ +battfake -1 +``` +## Example + +For Herobrine, the minimum battery level to boot the AP without AC is 2 percent +of the battery capacity and the minimum AC power to boot the AP with a battery +is set to 10000 milliwats. + +``` +CONFIG_PLATFORM_EC_CHARGER_MIN_BAT_PCT_FOR_POWER_ON=2 +CONFIG_PLATFORM_EC_CHARGER_MIN_POWER_MW_FOR_POWER_ON=10000 +``` + +[AP]: ../ec_terms.md#ap +[Kconfig.ap_power]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/Kconfig.ap_power diff --git a/docs/zephyr/zephyr_battery.md b/docs/zephyr/zephyr_battery.md index 6b084bf95f..c84bcc3b8e 100644 --- a/docs/zephyr/zephyr_battery.md +++ b/docs/zephyr/zephyr_battery.md @@ -50,7 +50,7 @@ Example: ``` -Here `vendor_part` will be the default battery type. If this node label is +Here `vendor_part` will be the default battery type. If this [*node label*] is present in the overlay, the [DEFAULT_BATTERY_TYPE] is set in the battery shim code with the labeled battery type. The `vendor` and `part` references must match an existing battery defined in [battery bindings directory]. @@ -137,6 +137,10 @@ requires the battery module for correct operation. ## Testing and Debugging +### EC Console Commands + +#### battery + The `battery` [EC console command] may be invoked to check battery information on a flashed board. @@ -169,17 +173,101 @@ full_factor:0.97 shutdown_soc:4 % ``` +#### pwr_avg + +The `pwr_avg` [EC console command] logs the battery charging rate by querying +the battery fuel gauge driver. + +Example output of `uart:~$ pwr_avg`: + +Charging + +``` +mv = 13073 +ma = 439 +mw = 573 +``` + +Discharging + +``` +mv = 12824 +ma = -146 +mw = -1872 +``` + +Note: A fully charged board may report `ma = 0` and `mw = 0` average rates. + +#### chgstate + +The `chgstate` [EC console command] may be invoked to debug and manipulate machine +charging state. + +Example output of `uart:~$ chgstate`: + +``` +state = charge +ac = 1 +batt_is_charging = 1 +chg.*: + voltage = 13200mV + current = 0mA + input_current = 3000mA + status = 0xc010 + option = 0x2830004 + flags = 0x0 +batt.*: + temperature = 26C + state_of_charge = 100% + voltage = 13037mV + current = 0mA + desired_voltage = 0mV + desired_current = 0mA + flags = 0x2 + remaining_capacity = 4436mAh + full_capacity = 4436mAh + is_present = YES +requested_voltage = 0mV +requested_current = 0mA +chg_ctl_mode = 0 +manual_voltage = -1 +manual_current = -1 +user_current_limit = -1mA +battery_seems_to_be_dead = 0 +battery_seems_to_be_disconnected = 0 +battery_was_removed = 0 +debug output = off +``` + +### AP Console Commands (ectool) + +#### chargestate + +The `chargestate` [ectool] command may be invoked to debug and manipulate +machine charging state. + +Usage output of `uart: # ectool chargestate`: + +``` +Usage: + chargestate show - show current state + chargestate param NUM [VALUE] - get/set param NUM + chargestate param help - show known param NUMs +``` + <!-- Reference Links --> +[CONFIG_PLATFORM_EC_BATTERY_PRESENT_CUSTOM]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/Kconfig.battery?q=%22PLATFORM_EC_BATTERY_PRESENT_CUSTOM%22&ss=chromiumos [DEFAULT_BATTERY_TYPE]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/shim/src/battery.c?q=%22DEFAULT_BATTERY_TYPE%22&ss=chromiumos [EC console command]: https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/README.md#useful-ec-console-commands [Example CL adding a new battery]: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3312506/ [Example CL enabling batteries on a board]: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3200068/ [Kconfig.battery]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/Kconfig.battery -[CONFIG_PLATFORM_EC_BATTERY_PRESENT_CUSTOM]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/Kconfig.battery?q=%22PLATFORM_EC_BATTERY_PRESENT_CUSTOM%22&ss=chromiumos [Zephyr I2C]: zephyr_i2c.md#Mapping-legacy-I2C-port-numbers-to-Zephyr-devicetree-nodes [Zephyr gpios]: zephyr_gpio.md#Devicetree-Nodes [battery bindings directory]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/dts/bindings/battery/ [battery-smart enum]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/dts/bindings/battery/battery-smart.yaml?q=%22enum:%22&ss=chromiumos [cros-ec-i2c-port-base.yaml]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/dts/bindings/i2c/cros-ec-i2c-port-base.yaml +[ectool]: ../ap-ec-comm.md [task]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/shim/include/shimmed_task_id.h +[*node label*]: https://docs.zephyrproject.org/latest/build/dts/intro.html#dt-node-labels diff --git a/docs/zephyr/zephyr_gpio.md b/docs/zephyr/zephyr_gpio.md index 1d563513cd..5e70562ab9 100644 --- a/docs/zephyr/zephyr_gpio.md +++ b/docs/zephyr/zephyr_gpio.md @@ -24,7 +24,7 @@ the devicetree node with all GPIOs from this node (unless the `no-auto-init` property is present). Legacy C source code accesses GPIOs using the specified `enum-name` property as an enum name of the GPIO. -Zephyr based code uses the node label, an alias, or other node reference +Zephyr based code uses the [*node label*], an alias, or other node reference to identify the GPIO. Named GPIO properties: @@ -41,7 +41,7 @@ initialization time, and selectively enabled by code at some later time. The file [gpio-enum-name.yaml] defines the list of valid `enum-name` values. In the GPIO declaration use the lowercase net name from the schematic as the -*node name*, and the same net name prefixed with `gpio_` as *node label*. +*node name*, and the same net name prefixed with `gpio_` as [*node label*]. For example: ``` @@ -87,7 +87,7 @@ GPIOs references that are not in legacy common code should use the to access the GPIO. GPIOs are referenced in the `named-gpios` child nodes using the -node label (if one exists), an alias to a node label, or +[*node label*] (if one exists), an alias to a [*node label*], or indirectly as a node reference via as a `phandle` in another node. To facilitate this, all GPIO child nodes in `named-gpios` @@ -97,7 +97,7 @@ These pointers are accessible via the following macros: Macro | Argument | Description :------- | :---------- | :------- -`GPIO_DT_FROM_NODELABEL` | nodelabel | Uses a node label to reference the GPIO node. +`GPIO_DT_FROM_NODELABEL` | nodelabel | Uses a [*node label*] to reference the GPIO node. `GPIO_DT_FROM_NODE` | node | Uses a node id (referenced as a `phandle` in another node). `GPIO_DT_FROM_ALIAS` | alias | Uses an alias to a label on the GPIO node. @@ -279,7 +279,7 @@ Child nodes of this single node contain the following properties: Property | Description | Settings :------- | :---------- | :------- -`irq-pin` | A reference via a node label to the named-gpio that is associated with this interrupt. | `<&gpio_label>` +`irq-pin` | A reference via a [*node label*] to the named-gpio that is associated with this interrupt. | `<&gpio_label>` `flags` | The GPIO [interrupt flags](https://docs.zephyrproject.org/latest/reference/peripherals/gpio.html) that define how the interrupt is generated. | `GPIO_INT_<flags>` `handler` | The C name of the interrupt handler that handles the interrupt. | C function name. @@ -431,7 +431,7 @@ property `GPIO_ENTERING_RW`. val = gpio_get_level(GPIO_ENTERING_RW); ``` -Use the `node label` to reference the GPIO in other devicetree nodes: +Use the [*node label*] to reference the GPIO in other devicetree nodes: ``` my_node: my-node { @@ -456,3 +456,4 @@ project. [gpio.dts]: ../../zephyr/projects/volteer/volteer/gpio.dts [interrupts.dts]: ../../zephyr/projects/volteer/volteer/interrupts.dts [BUILD.py]: ../../zephyr/projects/volteer/volteer/BUILD.py +[*node label*]: https://docs.zephyrproject.org/latest/build/dts/intro.html#dt-node-labels
\ No newline at end of file diff --git a/docs/zephyr/zephyr_i2c.md b/docs/zephyr/zephyr_i2c.md index 4f001e4408..da54a373a5 100644 --- a/docs/zephyr/zephyr_i2c.md +++ b/docs/zephyr/zephyr_i2c.md @@ -47,7 +47,7 @@ Example enabling I2C0 and I2C3 at 100 KHz and 1 MHz, respectively. Nuvoton ECs use two devicetree nodes to describe the I2C buses used, an I2C controller and an I2C port. -Nuvoton I2C node labels use the following pattern: +Nuvoton I2C [*node labels*] use the following pattern: - I2C controller: `&i2c_ctrl<controller>` - I2C port: `&i2c<controller>_<port>` @@ -352,3 +352,4 @@ below: [`CONFIG_I2C_SHELL`]: https://docs.zephyrproject.org/latest/kconfig.html#CONFIG_I2C_SHELL [cros-ec-i2c-port-base.yaml]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/dts/bindings/i2c/cros-ec-i2c-port-base.yaml [volteer.dts]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/boards/arm/volteer/volteer.dts; +[*node labels*]: https://docs.zephyrproject.org/latest/build/dts/intro.html#dt-node-labels
\ No newline at end of file diff --git a/docs/zephyr/zephyr_new_board_checklist.md b/docs/zephyr/zephyr_new_board_checklist.md index f83aa3a188..eb4584af2c 100644 --- a/docs/zephyr/zephyr_new_board_checklist.md +++ b/docs/zephyr/zephyr_new_board_checklist.md @@ -25,7 +25,8 @@ Each feature includes the following sub-tasks: the feature. `Kconfig` options are enabled in one of the [project configuration files]. - **Devicetree Nodes** - This section details the devicetree nodes and - properties required by the feature. + properties required by the feature. The [Zephyr Introduction to Devicetree] + provides a conceptual overview of devicetree and how Zephyr uses it. - **Board Specific Code** - When present, this section details any C code that your project must implement. - **Threads** - This section details the threads created by the feature and @@ -53,7 +54,9 @@ EC Feature | Ne :-------------------------------------------------------------------------- | :-----------------: [Configure EC Chipset (TODO)](./zephyr_template.md) | yes [Configure AP to EC Communication](./zephyr_ap_ec_comm.md) | yes +[Configure AP Power Thresholds](./zephyr_ap_power.md) | yes [Configure AP Power Sequencing (TODO)](./zephyr_template.md) | yes +[Configure USB-A](./zephyr_usba.md) | no [Configure USB-C (TODO)](./zephyr_template.md) | yes [Configure Charger (TODO)](./zephyr_template.md) | yes [Configure I2C Buses](./zephyr_i2c.md) | yes @@ -66,3 +69,5 @@ EC Feature | Ne [Configure BC1.2 Charger Detector (TODO)](./zephyr_template.md) | no [Configure ADC](./zephyr_adc.md) | no [Configure Temperature Sensors](./zephyr_temperature_sensor.md) | no + +[Zephyr Introduction to Devicetree]: https://docs.zephyrproject.org/latest/build/dts/intro.html diff --git a/docs/zephyr/zephyr_template.md b/docs/zephyr/zephyr_template.md index f75883eec9..f36c9f90da 100644 --- a/docs/zephyr/zephyr_template.md +++ b/docs/zephyr/zephyr_template.md @@ -8,21 +8,19 @@ ## Kconfig Options -*List the Kconfig options that enable the feature and list any sub-configuration -options that control the behavior of the feature.* - -Kconfig Option | Default | Documentation -:------------------------------------- | :-----: | :------------ -`CONFIG_PLATFORM_EC_<option>` | y/n | [zephyr/Kconfig](../zephyr/Kconfig) - -Kconfig sub-option | Default | Documentation -:------------------------------------- | :-----: | :------------ -`CONFIG_PLATFORM_EC_<option>` | y/n | [zephyr/Kconfig](../zephyr/Kconfig) +*Link to the file providing all the Kconfig options related to the feature. If +the Kconfig options are not currently in a standalone file, consider moving the +related Kconfigs into their own file.* +*Example CL moving I2C related configs into a new file: https://crrev.com/c/3575081* *Note - Avoid documenting `CONFIG_` options in the markdown as the relevant -`Kconfig*` contains the authoritative definition. Link directly to the Kconfig -option in source like this: [I2C Passthru Restricted].* +`Kconfig*` contains the authoritative definition. If there is one main Kconfig +that must be enabled for the feature, mention it in this section. See the [I2C +documentation](zephyr_i2c.md#kconfig-options) for an example.* + +*If the `Kconfig` file does not provide sufficient help descriptions, please fix +them.* ## Devicetree Nodes @@ -44,6 +42,9 @@ compile and run. For many features, this can section can be empty.* *Provide any tips for testing and debugging the EC feature.* +*It's especially helpful to document EC console commands and `ectool` commands +from the AP in this section. Please provide example output.* + ## Example *Provide code snippets from a working board to walk the user through diff --git a/docs/zephyr/zephyr_usba.md b/docs/zephyr/zephyr_usba.md new file mode 100644 index 0000000000..ce66125905 --- /dev/null +++ b/docs/zephyr/zephyr_usba.md @@ -0,0 +1,78 @@ +# Zephyr USBA Configuration + +[TOC] + +## Overview + +[USBA] is used to configure the number of USB Type-A ports in the system and +optional control of the power supplied by said ports. + +## Kconfig Options + +`CONFIG_PLATFORM_EC_USBA` enables support for USB-A ports in the EC application. +Refer to [Kconfig.usba] for all sub-options controlling USB-A ports. + +## Devicetree Nodes + +By default, for each USB Type-A port, a GPIO pin is required to control when power +is supplied to the port. The GPIO pins are described in Device Tree nodes. + +Refer to the [named-gpios.yaml] and [cros-ec,usba-port-enable-pins.yaml] child-binding +files for details about gpio properties. + +## Board Specific Code + +none + +## Threads + +When `CONFIG_PLATFORM_EC_USB_PORT_POWER_DUMB=y`, then the EC application automatically +powers up USB-A ports when the AP chipset starts up and powers off the USB-A ports +when the AP chipset shuts down. + +## Testing and Debugging + +Use the gpioset console command to manually enable and disable the USB Type-A port power. + +`gpioset` usage: gpioset <pin_name> <0 | 1> + +The `usbchargemode` console command is used to enable and disable charging +from the USB Type-A port. + +* For dumb power ports: `usbchargemode` <port> <on | off> +* For smart power ports: `usbchargemode` <port> <0 | 1 | 2 | 3> <0 | 1> + +Charging from USB Type-A ports can be controlled from the AP using ectool `usbchargemode`. + +`ectool usbchargemode` <port> <disabled | SDP | CDP | DCP> [inhibit_charge] + +Refer to the Application Processor to EC communication for more information about using[ ectool]. + +## Example + +The Herobrine board has one USB Type-A port: + +The following configures the project for one port. + +``` +`CONFIG_PLATFORM_EC_USB_PORT_POWER_DUMB=y` +``` + +The following device tree node configures the gpio pin. + +``` +gpio_en_usb_a_5v: en_usb_a_5v { + gpios = <&gpiof 0 GPIO_OUT_LOW>; +}; + +usba-port-enable-list { + compatible = "cros-ec,usba-port-enable-pins"; + enable-pins = <&gpio_en_usb_a_5v>; +}; +``` + +[USBA]: ../ec_terms.md#usba +[Kconfig.usba]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/Kconfig.usba +[named-gpios.yaml]: ../../zephyr/dts/bindings/gpio/named-gpios.yaml +[cros-ec,usba-port-enable-pins.yaml]: ../../zephyr/dts/bindings/gpio/cros-ec,usba-port-enable-pins.yaml +[ectool]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/util/ectool.c;?q=function:ms_help&ss=chromiumos diff --git a/driver/charger/isl923x.c b/driver/charger/isl923x.c index 7861ec95bc..c1e4f203fd 100644 --- a/driver/charger/isl923x.c +++ b/driver/charger/isl923x.c @@ -98,6 +98,7 @@ static int learn_mode; K_MUTEX_DEFINE(control1_mutex_isl923x); static enum ec_error_list isl923x_discharge_on_ac(int chgnum, int enable); +static enum ec_error_list isl923x_discharge_on_ac_weak_disable(int chgnum); /* Charger parameters */ static const struct charger_info isl9237_charger_info = { @@ -395,8 +396,7 @@ static enum ec_error_list isl923x_set_mode(int chgnum, int mode) * See crosbug.com/p/51196. Always disable learn mode unless it was set * explicitly. */ - if (!learn_mode) - rv = isl923x_discharge_on_ac(chgnum, 0); + rv = isl923x_discharge_on_ac_weak_disable(chgnum); /* ISL923X does not support inhibit mode setting. */ return rv; @@ -763,13 +763,15 @@ init_fail: CPRINTS("%s init failed!", CHARGER_NAME); } -static enum ec_error_list isl923x_discharge_on_ac(int chgnum, int enable) +/* + * Writes to ISL923X_REG_CONTROL1, unsafe as it does not lock + * control1_mutex_isl923x. + */ +static enum ec_error_list isl923x_discharge_on_ac_unsafe(int chgnum, int enable) { int rv; int control1; - mutex_lock(&control1_mutex_isl923x); - rv = raw_read16(chgnum, ISL923X_REG_CONTROL1, &control1); if (rv) goto out; @@ -782,9 +784,32 @@ static enum ec_error_list isl923x_discharge_on_ac(int chgnum, int enable) rv = raw_write16(chgnum, ISL923X_REG_CONTROL1, control1); - learn_mode = !rv && enable; + if (!rv) + learn_mode = enable; out: + return rv; +} + +static enum ec_error_list isl923x_discharge_on_ac(int chgnum, int enable) +{ + int rv; + + mutex_lock(&control1_mutex_isl923x); + rv = isl923x_discharge_on_ac_unsafe(chgnum, enable); + mutex_unlock(&control1_mutex_isl923x); + return rv; +} + +/* Disables discharge on ac only if it wasn't explicitly enabled. */ +static enum ec_error_list isl923x_discharge_on_ac_weak_disable(int chgnum) +{ + int rv = 0; + + mutex_lock(&control1_mutex_isl923x); + if (!learn_mode) + rv = isl923x_discharge_on_ac_unsafe(chgnum, 0); + mutex_unlock(&control1_mutex_isl923x); return rv; } diff --git a/driver/charger/isl9241.c b/driver/charger/isl9241.c index 4fbb137871..b2a061d696 100644 --- a/driver/charger/isl9241.c +++ b/driver/charger/isl9241.c @@ -63,6 +63,9 @@ static const struct charger_info isl9241_charger_info = { }; static enum ec_error_list isl9241_discharge_on_ac(int chgnum, int enable); +static enum ec_error_list isl9241_discharge_on_ac_unsafe(int chgnum, + int enable); +static enum ec_error_list isl9241_discharge_on_ac_weak_disable(int chgnum); static inline enum ec_error_list isl9241_read(int chgnum, int offset, int *value) @@ -199,14 +202,12 @@ static enum ec_error_list isl9241_set_mode(int chgnum, int mode) int rv; /* - * See crosbug.com/p/51196. Always disable learn mode unless it was set - * explicitly. + * See crosbug.com/p/51196. + * Disable learn mode if it wasn't explicitly enabled. */ - if (!learn_mode) { - rv = isl9241_discharge_on_ac(chgnum, 0); - if (rv) - return rv; - } + rv = isl9241_discharge_on_ac_weak_disable(chgnum); + if (rv) + return rv; /* * Charger inhibit @@ -308,18 +309,42 @@ static enum ec_error_list isl9241_post_init(int chgnum) return EC_SUCCESS; } -static enum ec_error_list isl9241_discharge_on_ac(int chgnum, int enable) +/* + * Writes to ISL9241_REG_CONTROL1, unsafe as it does not lock + * control1_mutex_isl9241. + */ +static enum ec_error_list isl9241_discharge_on_ac_unsafe(int chgnum, + int enable) { - int rv; - - mutex_lock(&control1_mutex_isl9241); - - rv = isl9241_update(chgnum, ISL9241_REG_CONTROL1, + int rv = isl9241_update(chgnum, ISL9241_REG_CONTROL1, ISL9241_CONTROL1_LEARN_MODE, (enable) ? MASK_SET : MASK_CLR); if (!rv) learn_mode = enable; + return rv; +} + +/* Disables discharge on ac only if it wasn't explicitly enabled. */ +static enum ec_error_list isl9241_discharge_on_ac_weak_disable(int chgnum) +{ + int rv = 0; + + mutex_lock(&control1_mutex_isl9241); + if (!learn_mode) { + rv = isl9241_discharge_on_ac_unsafe(chgnum, 0); + } + + mutex_unlock(&control1_mutex_isl9241); + return rv; +} + +static enum ec_error_list isl9241_discharge_on_ac(int chgnum, int enable) +{ + int rv = 0; + + mutex_lock(&control1_mutex_isl9241); + rv = isl9241_discharge_on_ac_unsafe(chgnum, enable); mutex_unlock(&control1_mutex_isl9241); return rv; } diff --git a/driver/charger/rt9490.c b/driver/charger/rt9490.c index e2d2b76b0b..e3eee4ebad 100644 --- a/driver/charger/rt9490.c +++ b/driver/charger/rt9490.c @@ -264,7 +264,7 @@ static inline int rt9490_enable_jeita(int chgnum, bool en) en ? MASK_CLR : MASK_SET); } -static inline int rt9490_enable_adc(int chgnum, bool en) +int rt9490_enable_adc(int chgnum, bool en) { return rt9490_update8(chgnum, RT9490_REG_ADC_CTRL, RT9490_ADC_EN, en ? MASK_SET : MASK_CLR); diff --git a/driver/charger/rt9490.h b/driver/charger/rt9490.h index 0ea7746d8e..a6ace8c1eb 100644 --- a/driver/charger/rt9490.h +++ b/driver/charger/rt9490.h @@ -4,6 +4,8 @@ * * Richtek 5A 1-4 cell buck-boost switching battery charger driver. */ +#include <stdbool.h> + #ifndef __CROS_EC_RT9490_H #define __CROS_EC_RT9490_H @@ -241,4 +243,6 @@ extern const struct bc12_drv rt9490_bc12_drv; void rt9490_interrupt(int port); +int rt9490_enable_adc(int chgnum, bool en); + #endif /* __CROS_EC_RT9490_H */ diff --git a/driver/led/aw20198.c b/driver/led/aw20198.c index 5537556ffa..1c6bc4933c 100644 --- a/driver/led/aw20198.c +++ b/driver/led/aw20198.c @@ -143,11 +143,6 @@ static int aw20198_init(struct rgbkbd *ctx) rv = aw20198_reset(ctx); msleep(3); - rv |= aw20198_enable(ctx, true); - if (rv) { - CPRINTS("Failed to enable or reset (%d)", rv); - return rv; - } /* Read chip ID, assuming page is still 0. */ rv = aw20198_read(ctx, AW20198_REG_RSTN, &id); diff --git a/driver/led/is31fl3743b.c b/driver/led/is31fl3743b.c index f1a8833318..5539eee9b0 100644 --- a/driver/led/is31fl3743b.c +++ b/driver/led/is31fl3743b.c @@ -164,11 +164,6 @@ static int is31fl3743b_init(struct rgbkbd *ctx) rv = is31fl3743b_reset(ctx); msleep(3); - rv |= is31fl3743b_enable(ctx, true); - if (rv) { - CPRINTS("Failed to enable or reset (%d)", rv); - return rv; - } if (IS_ENABLED(CONFIG_RGB_KEYBOARD_DEBUG)) { uint8_t val; diff --git a/extra/usb_updater/usb_updater2.c b/extra/usb_updater/usb_updater2.c index 12ee1615fc..81cf48a680 100644 --- a/extra/usb_updater/usb_updater2.c +++ b/extra/usb_updater/usb_updater2.c @@ -354,7 +354,7 @@ static int find_interface(struct usb_endpoint *uep) for (j = 0; j < iface0->num_altsetting; j++) { iface = &iface0->altsetting[j]; if (find_endpoint(iface, uep)) { - iface_num = i; + iface_num = iface->bInterfaceNumber; goto out; } } diff --git a/firmware_builder.py b/firmware_builder.py index 6229e87539..625cb5166a 100755 --- a/firmware_builder.py +++ b/firmware_builder.py @@ -78,6 +78,14 @@ def build(opts): with open(opts.metrics, 'w') as f: f.write(json_format.MessageToJson(metric_list)) + # Ensure that there are no regressions for boards that build successfully + # with clang: b/172020503. + cmd = ['./util/build_with_clang.py'] + print(f'# Running {" ".join(cmd)}.') + subprocess.run(cmd, + cwd=os.path.dirname(__file__), + check=True) + UNITS = { 'B': 1, diff --git a/include/ec_commands.h b/include/ec_commands.h index df5fee3250..1aff487bbe 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -7094,6 +7094,8 @@ enum rgbkbd_state { RGBKBD_STATE_RESET = 0, /* RGB keyboard is initialized but not enabled. */ RGBKBD_STATE_INITIALIZED, + /* RGB keyboard is disabled. */ + RGBKBD_STATE_DISABLED, /* RGB keyboard is enabled and ready to receive a command. */ RGBKBD_STATE_ENABLED, diff --git a/include/rgb_keyboard.h b/include/rgb_keyboard.h index 0500ce859f..2c6a550e7b 100644 --- a/include/rgb_keyboard.h +++ b/include/rgb_keyboard.h @@ -12,6 +12,8 @@ /* Use this instead of '3' for readability where applicable. */ #define SIZE_OF_RGB sizeof(struct rgb_s) +#define RGBKBD_MAX_GCC_LEVEL 0xff + enum rgbkbd_demo { RGBKBD_DEMO_OFF = 0, RGBKBD_DEMO_FLOW = 1, @@ -37,6 +39,8 @@ struct rgbkbd { const struct rgbkbd_cfg * const cfg; /* Current state of the port */ enum rgbkbd_state state; + /* Global current control (a.k.a. backlight brightness) */ + uint8_t gcc; /* Buffer containing color info for each dot. */ struct rgb_s *buf; }; @@ -173,3 +177,17 @@ __override_proto void board_enable_rgb_keyboard(bool enable); */ extern const uint8_t rgbkbd_map[]; extern const size_t rgbkbd_map_size; + +/** + * Set/get global brightness of the RGB keyboard. + * + * @param gcc Brightness level 0 ~ RGBKBD_MAX_GCC_LEVEL. + * @return enum ec_error_list; + */ +int rgbkbd_set_global_brightness(uint8_t gcc); +int rgbkbd_get_global_brightness(uint8_t *gcc); + +/* + * Driver for keyboard_backlight. + */ +extern const struct kblight_drv kblight_rgbkbd; diff --git a/include/task.h b/include/task.h index b23fe869b1..4e0ff04697 100644 --- a/include/task.h +++ b/include/task.h @@ -469,16 +469,4 @@ struct irq_def { #endif /* CONFIG_COMMON_RUNTIME */ #endif /* !CONFIG_ZEPHYR */ -#if defined(CONFIG_ZEPHYR) && defined(TEST_BUILD) -#include <kernel.h> - -/** - * @brief Get the Zephyr thread ID for the given task - * - * @param cros_tid A valid cros TASK_ID_* entry - * @return The Zephyr thread ID - */ -k_tid_t task_get_zephyr_tid(size_t cros_tid); -#endif /* CONFIG_ZEPHYR && TEST_BUILD */ - #endif /* __CROS_EC_TASK_H */ diff --git a/power/amd_x86.c b/power/amd_x86.c index c3698bde5d..2a35849039 100644 --- a/power/amd_x86.c +++ b/power/amd_x86.c @@ -252,13 +252,6 @@ __override void power_chipset_handle_sleep_hang( host_set_single_event(EC_HOST_EVENT_HANG_DETECT); } -static void handle_chipset_suspend(void) -{ - /* Clear masks before any hooks are run for suspend. */ - lpc_s0ix_suspend_clear_masks(); -} -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, handle_chipset_suspend, HOOK_PRIO_FIRST); - static void handle_chipset_reset(void) { if (chipset_in_state(CHIPSET_STATE_STANDBY)) { @@ -296,6 +289,11 @@ __override void power_chipset_handle_host_sleep_event( #ifdef CONFIG_POWER_S0IX if (state == HOST_SLEEP_EVENT_S0IX_SUSPEND) { /* + * Clear event mask for SMI and SCI first to avoid host being + * interrupted while suspending. + */ + lpc_s0ix_suspend_clear_masks(); + /* * Indicate to power state machine that a new host event for * s0ix/s3 suspend has been received and so chipset suspend * notification needs to be sent to listeners. diff --git a/test/motion_sense_fifo.c b/test/motion_sense_fifo.c index 1d6602650c..afa9a4f5cf 100644 --- a/test/motion_sense_fifo.c +++ b/test/motion_sense_fifo.c @@ -293,6 +293,58 @@ static int test_spread_data_in_window(void) return EC_SUCCESS; } +static int test_spread_data_on_overflow(void) +{ + const uint32_t now = __hw_clock_source_read(); + const int fill_count = (CONFIG_ACCEL_FIFO_SIZE / 2) - 1; + int i, read_count; + + /* Set up the sensors */ + motion_sensors[0].collection_rate = 20; /* us */ + motion_sensors[0].oversampling_ratio = 1; + motion_sensors[1].oversampling_ratio = 1; + + /* Add 1 sample for sensor [1]. This will be evicted. */ + data->sensor_num = 1; + motion_sense_fifo_stage_data(data, motion_sensors + 1, 3, 0); + + /* + * Fill the rest of the fifo, every 2 entries will have the same + * timestamp simulating have 2 entries on the hardware FIFO per read. + */ + data->sensor_num = 0; + for (i = 0; i < fill_count; i++) { + int ts = now - ((fill_count - i) / 2) * 10; + + motion_sense_fifo_stage_data(data, motion_sensors, 3, ts); + } + + /* Insert an async event which also causes a commit */ + motion_sense_fifo_insert_async_event(motion_sensors, ASYNC_EVENT_FLUSH); + + read_count = + motion_sense_fifo_read(sizeof(data), 4, data, &data_bytes_read); + + /* Verify that we read 4 entries */ + TEST_EQ(read_count, 4, "%d"); + + /* Verify that entries 0 and 2 are timestamps (1 and 3 are data) */ + TEST_BITS_SET(data[0].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); + TEST_BITS_SET(data[2].flags, MOTIONSENSE_SENSOR_FLAG_TIMESTAMP); + + /* + * Verify that the first read entry is the first one added in the for + * loop above. + */ + TEST_EQ(data[0].sensor_num, 0, "%u"); + TEST_EQ(data[0].timestamp, now - ((fill_count - 1) / 2) * 10, "%u"); + + /* Verify that the timestamp was spread */ + TEST_NE(data[0].timestamp, data[2].timestamp, "%u"); + + return EC_SUCCESS; +} + static int test_spread_data_by_collection_rate(void) { const uint32_t now = __hw_clock_source_read(); @@ -411,6 +463,7 @@ void run_test(int argc, char **argv) RUN_TEST(test_add_data_no_spreading_when_different_sensors); RUN_TEST(test_add_data_no_spreading_different_timestamps); RUN_TEST(test_spread_data_in_window); + RUN_TEST(test_spread_data_on_overflow); RUN_TEST(test_spread_data_by_collection_rate); RUN_TEST(test_spread_double_commit_same_timestamp); RUN_TEST(test_commit_non_data_or_timestamp_entries); diff --git a/test/run_device_tests.py b/test/run_device_tests.py index fbe2ed31a5..f7c8ae2725 100755 --- a/test/run_device_tests.py +++ b/test/run_device_tests.py @@ -26,7 +26,7 @@ import time from concurrent.futures.thread import ThreadPoolExecutor from enum import Enum from pathlib import Path -from typing import Optional, BinaryIO, List, Dict +from typing import Optional, BinaryIO, List # pylint: disable=import-error import colorama # type: ignore[import] @@ -104,11 +104,11 @@ class BoardConfig: class TestConfig: """Configuration for a given test.""" - def __init__(self, name, image_to_use=ImageType.RW, finish_regexes=None, - fail_regexes=None, toggle_power=False, test_args=None, - num_flash_attempts=2, timeout_secs=10, - enable_hw_write_protect=False, ro_image=None, - build_board=None): + def __init__(self, test_name, image_to_use=ImageType.RW, + finish_regexes=None, fail_regexes=None, toggle_power=False, + test_args=None, num_flash_attempts=2, timeout_secs=10, + enable_hw_write_protect=False, ro_image=None, build_board=None, + config_name=None): if test_args is None: test_args = [] if finish_regexes is None: @@ -116,8 +116,11 @@ class TestConfig: if fail_regexes is None: fail_regexes = [SINGLE_CHECK_FAILED_REGEX, ALL_TESTS_FAILED_REGEX, ASSERTION_FAILURE_REGEX] + if config_name is None: + config_name = test_name - self.name = name + self.test_name = test_name + self.config_name = config_name self.image_to_use = image_to_use self.finish_regexes = finish_regexes self.fail_regexes = fail_regexes @@ -139,105 +142,72 @@ class AllTests: """All possible tests.""" @staticmethod - def get(board_config: BoardConfig) -> Dict[str, TestConfig]: + def get(board_config: BoardConfig) -> List[TestConfig]: public_tests = AllTests.get_public_tests(board_config) private_tests = AllTests.get_private_tests() - # Make sure there are no conflicts - # pylint: disable=dict-keys-not-iterating - overwritten_tests = public_tests.keys() & private_tests.keys() - # pylint: enable=dict-keys-not-iterating - if overwritten_tests: - err = 'Public test overwritten by private one with the same name: ' - err += str(overwritten_tests) - raise RuntimeError(err) - - return {**public_tests, **private_tests} + return public_tests + private_tests @staticmethod - def get_public_tests(board_config: BoardConfig) -> Dict[str, TestConfig]: - tests = { - 'aes': - TestConfig(name='aes'), - 'cec': - TestConfig(name='cec'), - 'cortexm_fpu': - TestConfig(name='cortexm_fpu'), - 'crc': - TestConfig(name='crc'), - 'flash_physical': - TestConfig(name='flash_physical', image_to_use=ImageType.RO, - toggle_power=True), - 'flash_write_protect': - TestConfig(name='flash_write_protect', - image_to_use=ImageType.RO, - toggle_power=True, enable_hw_write_protect=True), - 'fpsensor_hw': - TestConfig(name='fpsensor_hw'), - 'fpsensor_spi_ro': - TestConfig(name='fpsensor', image_to_use=ImageType.RO, - test_args=['spi']), - 'fpsensor_spi_rw': - TestConfig(name='fpsensor', test_args=['spi']), - 'fpsensor_uart_ro': - TestConfig(name='fpsensor', image_to_use=ImageType.RO, - test_args=['uart']), - 'fpsensor_uart_rw': - TestConfig(name='fpsensor', test_args=['uart']), - 'mpu_ro': - TestConfig(name='mpu', - image_to_use=ImageType.RO, - finish_regexes=[board_config.mpu_regex]), - 'mpu_rw': - TestConfig(name='mpu', - finish_regexes=[board_config.mpu_regex]), - 'mutex': - TestConfig(name='mutex'), - 'pingpong': - TestConfig(name='pingpong'), - 'printf': - TestConfig(name='printf'), - 'queue': - TestConfig(name='queue'), - 'rollback_region0': - TestConfig(name='rollback', finish_regexes=[ - board_config.rollback_region0_regex], - test_args=['region0']), - 'rollback_region1': - TestConfig(name='rollback', finish_regexes=[ - board_config.rollback_region1_regex], - test_args=['region1']), - 'rollback_entropy': - TestConfig(name='rollback_entropy', image_to_use=ImageType.RO), - 'rtc': - TestConfig(name='rtc'), - 'sha256': - TestConfig(name='sha256'), - 'sha256_unrolled': - TestConfig(name='sha256_unrolled'), - 'static_if': - TestConfig(name='static_if'), - 'system_is_locked_wp_on': - TestConfig(name='system_is_locked', test_args=['wp_on'], - toggle_power=True, enable_hw_write_protect=True), - 'system_is_locked_wp_off': - TestConfig(name='system_is_locked', test_args=['wp_off'], - toggle_power=True, enable_hw_write_protect=False), - 'timer_dos': - TestConfig(name='timer_dos'), - 'utils': - TestConfig(name='utils', timeout_secs=20), - 'utils_str': - TestConfig(name='utils_str'), - } + def get_public_tests(board_config: BoardConfig) -> List[TestConfig]: + tests = [ + TestConfig(test_name='aes'), + TestConfig(test_name='cec'), + TestConfig(test_name='cortexm_fpu'), + TestConfig(test_name='crc'), + TestConfig(test_name='flash_physical', image_to_use=ImageType.RO, + toggle_power=True), + TestConfig(test_name='flash_write_protect', + image_to_use=ImageType.RO, + toggle_power=True, enable_hw_write_protect=True), + TestConfig(test_name='fpsensor_hw'), + TestConfig(config_name='fpsensor_spi_ro', test_name='fpsensor', + image_to_use=ImageType.RO, test_args=['spi']), + TestConfig(config_name='fpsensor_spi_rw', test_name='fpsensor', + test_args=['spi']), + TestConfig(config_name='fpsensor_uart_ro', test_name='fpsensor', + image_to_use=ImageType.RO, test_args=['uart']), + TestConfig(config_name='fpsensor_uart_rw', test_name='fpsensor', + test_args=['uart']), + TestConfig(config_name='mpu_ro', test_name='mpu', + image_to_use=ImageType.RO, + finish_regexes=[board_config.mpu_regex]), + TestConfig(config_name='mpu_rw', test_name='mpu', + finish_regexes=[board_config.mpu_regex]), + TestConfig(test_name='mutex'), + TestConfig(test_name='pingpong'), + TestConfig(test_name='printf'), + TestConfig(test_name='queue'), + TestConfig(config_name='rollback_region0', test_name='rollback', + finish_regexes=[board_config.rollback_region0_regex], + test_args=['region0']), + TestConfig(config_name='rollback_region1', test_name='rollback', + finish_regexes=[board_config.rollback_region1_regex], + test_args=['region1']), + TestConfig(test_name='rollback_entropy', image_to_use=ImageType.RO), + TestConfig(test_name='rtc'), + TestConfig(test_name='sha256'), + TestConfig(test_name='sha256_unrolled'), + TestConfig(test_name='static_if'), + TestConfig(config_name='system_is_locked_wp_on', + test_name='system_is_locked', test_args=['wp_on'], + toggle_power=True, enable_hw_write_protect=True), + TestConfig(config_name='system_is_locked_wp_off', + test_name='system_is_locked', test_args=['wp_off'], + toggle_power=True, enable_hw_write_protect=False), + TestConfig(test_name='timer_dos'), + TestConfig(test_name='utils', timeout_secs=20), + TestConfig(test_name='utils_str'), + ] if board_config.name == BLOONCHIPPER: - tests['stm32f_rtc'] = TestConfig(name='stm32f_rtc') + tests.append(TestConfig(test_name='stm32f_rtc')) # Run panic data tests for all boards and RO versions. for variant_name, variant_info in board_config.variants.items(): - tests['panic_data_' + variant_name] = ( - TestConfig(name='panic_data', + tests.append( + TestConfig(config_name='panic_data_' + variant_name, + test_name='panic_data', fail_regexes=[SINGLE_CHECK_FAILED_REGEX, ALL_TESTS_FAILED_REGEX], ro_image=variant_info.get('ro_image_path'), @@ -246,24 +216,24 @@ class AllTests: return tests @staticmethod - def get_private_tests() -> Dict[str, TestConfig]: + def get_private_tests() -> List[TestConfig]: # Return all private tests, if the folder exists - tests = {} + tests = [] try: current_dir = os.path.dirname(__file__) private_dir = os.path.join(current_dir, os.pardir, 'private/test') have_private = os.path.isdir(private_dir) if not have_private: - return {} + return [] sys.path.append(private_dir) import private_tests # pylint: disable=import-error - for test_id, test_args in private_tests.tests.items(): - tests[test_id] = TestConfig(**test_args) + for test_args in private_tests.tests: + tests.append(TestConfig(**test_args)) # Catch all exceptions to avoid disruptions in public repo except BaseException as e: logging.debug('Failed to get list of private tests: %s', str(e)) logging.debug('Ignore error and continue.') - return {} + return [] return tests @@ -572,14 +542,14 @@ def run_test(test: TestConfig, console: str, executor: ThreadPoolExecutor) ->\ def get_test_list(config: BoardConfig, test_args) -> List[TestConfig]: """Get a list of tests to run.""" if test_args == 'all': - return list(AllTests.get(config).values()) + return AllTests.get(config) test_list = [] for t in test_args: logging.debug('test: %s', t) test_regex = re.compile(t) - tests = [v for k, v in AllTests.get(config).items() - if test_regex.fullmatch(k)] + tests = [test for test in AllTests.get(config) + if test_regex.fullmatch(test.config_name)] if not tests: logging.error('Unable to find test config for "%s"', t) sys.exit(1) @@ -643,7 +613,9 @@ def main(): e = ThreadPoolExecutor(max_workers=1) test_list = get_test_list(board_config, args.tests) - logging.debug('Running tests: %s', [t.name for t in test_list]) + logging.debug( + 'Running tests: %s', [ + test.config_name for test in test_list]) for test in test_list: build_board = args.board @@ -653,10 +625,10 @@ def main(): build_board = test.build_board # build test binary - build(test.name, build_board, args.compiler) + build(test.test_name, build_board, args.compiler) - image_path = os.path.join(EC_DIR, 'build', build_board, test.name, - test.name + '.bin') + image_path = os.path.join(EC_DIR, 'build', build_board, test.test_name, + test.test_name + '.bin') if test.ro_image is not None: try: @@ -692,7 +664,7 @@ def main(): hw_write_protect(test.enable_hw_write_protect) # run the test - logging.info('Running test: "%s"', test.name) + logging.info('Running test: "%s"', test.config_name) console = get_console(board_config) test.passed = run_test(test, console, executor=e) @@ -700,7 +672,7 @@ def main(): exit_code = 0 for test in test_list: # print results - print('Test "' + test.name + '": ', end='') + print('Test "' + test.config_name + '": ', end='') if test.passed: print(colorama.Fore.GREEN + 'PASSED') else: diff --git a/util/build_with_clang.py b/util/build_with_clang.py new file mode 100755 index 0000000000..5cc23d1012 --- /dev/null +++ b/util/build_with_clang.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 + +# 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. + +"""Build firmware with clang instead of gcc.""" +import logging +import os +import subprocess +import sys + + +# Add to this list as compilation errors are fixed for boards. +BOARDS_THAT_COMPILE_SUCCESSFULLY_WITH_CLANG = [ + 'dartmonkey', + 'bloonchipper', + 'nucleo-f412zg', + 'nucleo-h743zi', +] + + +def build(board_name: str) -> None: + """Build with clang for specified board.""" + logging.debug('Building board: "%s"', board_name) + + cmd = [ + 'make', + 'BOARD=' + board_name, + '-j', + ] + + logging.debug('Running command: "%s"', ' '.join(cmd)) + subprocess.run(cmd, env=dict(os.environ, CC='clang'), check=True) + + +def main() -> int: + logging.basicConfig(level='DEBUG') + for board in BOARDS_THAT_COMPILE_SUCCESSFULLY_WITH_CLANG: + build(board) + + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/util/ectool.c b/util/ectool.c index af116160e5..31e0f07631 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -7957,6 +7957,7 @@ int cmd_battery(int argc, char *argv[]) int rv, val; char *e; int index = 0; + uint8_t flags; if (argc > 2) { fprintf(stderr, "Usage: %s [index]\n", argv[0]); @@ -7983,6 +7984,8 @@ int cmd_battery(int argc, char *argv[]) return -1; } + flags = read_mapped_mem8(EC_MEMMAP_BATT_FLAG); + printf("Battery info:\n"); rv = read_mapped_string(EC_MEMMAP_BATT_MFGR, batt_text, @@ -8035,15 +8038,15 @@ int cmd_battery(int argc, char *argv[]) val = read_mapped_mem32(EC_MEMMAP_BATT_RATE); if (!is_battery_range(val)) goto cmd_error; - printf(" Present current %u mA\n", val); + printf(" Present current %u mA%s\n", val, + flags & EC_BATT_FLAG_DISCHARGING ? " (discharging)" : ""); val = read_mapped_mem32(EC_MEMMAP_BATT_CAP); if (!is_battery_range(val)) goto cmd_error; printf(" Remaining capacity %u mAh\n", val); - val = read_mapped_mem8(EC_MEMMAP_BATT_FLAG); - print_battery_flags(val); + print_battery_flags(flags); return 0; cmd_error: diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index df54406fa2..9a14c93731 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -516,7 +516,8 @@ zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_RTC "${PLATFORM_EC}/common/rtc.c") zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_MATH_UTIL "${PLATFORM_EC}/common/math_util.c") - +zephyr_library_sources_ifdef(CONFIG_AP_PWRSEQ_HOST_SLEEP + "${PLATFORM_EC}/power/host_sleep.c") # Switch to ec_shim library for all Zephyr sources set(ZEPHYR_CURRENT_LIBRARY ec_shim) diff --git a/zephyr/Kconfig.stacks b/zephyr/Kconfig.stacks index 6e6c336de9..88e00bb112 100644 --- a/zephyr/Kconfig.stacks +++ b/zephyr/Kconfig.stacks @@ -78,8 +78,8 @@ config TASK_PD_STACK_SIZE config TASK_PD_INT_STACK_SIZE default 1152 if SOC_SERIES_RISCV32_IT8XXX2 - default 736 if SOC_SERIES_NPCX7 - default 736 if SOC_SERIES_NPCX9 + default 880 if SOC_SERIES_NPCX7 + default 880 if SOC_SERIES_NPCX9 config TASK_USB_CHG_STACK_SIZE default 1152 if SOC_SERIES_RISCV32_IT8XXX2 diff --git a/zephyr/Kconfig.usba b/zephyr/Kconfig.usba index cca91ef787..c0cbdacdfe 100644 --- a/zephyr/Kconfig.usba +++ b/zephyr/Kconfig.usba @@ -15,8 +15,9 @@ menuconfig PLATFORM_EC_USBA if PLATFORM_EC_USBA -choice +choice PLATFORM_EC_USBA_PORT_POWER_TYPE prompt "Port power control mode" + default PLATFORM_EC_USB_PORT_POWER_DUMB config PLATFORM_EC_USB_PORT_POWER_DUMB bool "Dumb" diff --git a/zephyr/boards/arm/npcx7/npcx7_defconfig b/zephyr/boards/arm/npcx7/npcx7_defconfig index afebc2383d..cc1cd1eb6d 100644 --- a/zephyr/boards/arm/npcx7/npcx7_defconfig +++ b/zephyr/boards/arm/npcx7/npcx7_defconfig @@ -4,7 +4,6 @@ # Zephyr Kernel Configuration CONFIG_SOC_SERIES_NPCX7=y -CONFIG_SOC_LOG_LEVEL_ERR=y # Platform Configuration CONFIG_BOARD_NPCX7=y @@ -34,7 +33,6 @@ CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_PM_POLICY_CUSTOM=y CONFIG_UART_CONSOLE_INPUT_EXPIRED=y -CONFIG_NPCX_PM_TRACE=y # BBRAM CONFIG_BBRAM=y diff --git a/zephyr/boards/arm/npcx9/npcx9_defconfig b/zephyr/boards/arm/npcx9/npcx9_defconfig index ed1a44764b..18790143b0 100644 --- a/zephyr/boards/arm/npcx9/npcx9_defconfig +++ b/zephyr/boards/arm/npcx9/npcx9_defconfig @@ -5,7 +5,6 @@ # Zephyr Kernel Configuration CONFIG_SOC_SERIES_NPCX9=y CONFIG_SOC_NPCX9M3F=y -CONFIG_SOC_LOG_LEVEL_ERR=y # Platform Configuration CONFIG_BOARD_NPCX9=y @@ -35,7 +34,6 @@ CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_PM_POLICY_CUSTOM=y CONFIG_UART_CONSOLE_INPUT_EXPIRED=y -CONFIG_NPCX_PM_TRACE=y # BBRAM CONFIG_BBRAM=y diff --git a/zephyr/boards/arm/npcx_evb/npcx7_evb_defconfig b/zephyr/boards/arm/npcx_evb/npcx7_evb_defconfig index 828304e5c9..5f79c4ce8a 100644 --- a/zephyr/boards/arm/npcx_evb/npcx7_evb_defconfig +++ b/zephyr/boards/arm/npcx_evb/npcx7_evb_defconfig @@ -49,7 +49,6 @@ CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_PM_POLICY_CUSTOM=y CONFIG_UART_CONSOLE_INPUT_EXPIRED=y -CONFIG_NPCX_PM_TRACE=y # BBRAM CONFIG_BBRAM=y diff --git a/zephyr/boards/arm/npcx_evb/npcx9_evb_defconfig b/zephyr/boards/arm/npcx_evb/npcx9_evb_defconfig index ef0737a059..d4473b0f64 100644 --- a/zephyr/boards/arm/npcx_evb/npcx9_evb_defconfig +++ b/zephyr/boards/arm/npcx_evb/npcx9_evb_defconfig @@ -49,7 +49,6 @@ CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_PM_POLICY_CUSTOM=y CONFIG_UART_CONSOLE_INPUT_EXPIRED=y -CONFIG_NPCX_PM_TRACE=y # BBRAM CONFIG_BBRAM=y diff --git a/zephyr/boards/riscv/it8xxx2/it8xxx2.dts b/zephyr/boards/riscv/it8xxx2/it8xxx2.dts index dcc3f4a970..aeeda0a2fe 100644 --- a/zephyr/boards/riscv/it8xxx2/it8xxx2.dts +++ b/zephyr/boards/riscv/it8xxx2/it8xxx2.dts @@ -23,13 +23,6 @@ /* Override keyboard scanning */ soc { /delete-node/ kscan@f01d00; - - cros_kb_raw: cros-kb-raw@f01d00 { - compatible = "ite,it8xxx2-cros-kb-raw"; - reg = <0x00f01d00 0x29>; - interrupt-parent = <&intc>; - interrupts = <13 IRQ_TYPE_LEVEL_HIGH>; - }; }; }; diff --git a/zephyr/drivers/cros_kb_raw/cros_kb_raw_ite.c b/zephyr/drivers/cros_kb_raw/cros_kb_raw_ite.c index 61b1adcf3f..d5b84cb0fd 100644 --- a/zephyr/drivers/cros_kb_raw/cros_kb_raw_ite.c +++ b/zephyr/drivers/cros_kb_raw/cros_kb_raw_ite.c @@ -9,8 +9,11 @@ #include <drivers/cros_kb_raw.h> #include <drivers/clock_control.h> #include <drivers/gpio.h> +#include <drivers/interrupt_controller/wuc_ite_it8xxx2.h> +#include <dt-bindings/interrupt-controller/it8xxx2-wuc.h> #include <kernel.h> #include <soc.h> +#include <soc_dt.h> #include <soc/ite_it8xxx2/reg_def_cros.h> #include "ec_tasks.h" @@ -20,14 +23,29 @@ #include <logging/log.h> LOG_MODULE_REGISTER(cros_kb_raw, LOG_LEVEL_ERR); +#define KEYBOARD_KSI_PIN_COUNT IT8XXX2_DT_INST_WUCCTRL_LEN(0) #define KSOH_PIN_MASK (((1 << (KEYBOARD_COLS_MAX - 8)) - 1) & 0xff) /* Device config */ +struct cros_kb_raw_wuc_map_cfg { + /* WUC control device structure */ + const struct device *wucs; + /* WUC pin mask */ + uint8_t mask; +}; + struct cros_kb_raw_ite_config { /* keyboard scan controller base address */ - uintptr_t base; + struct kscan_it8xxx2_regs *base; /* Keyboard scan input (KSI) wake-up irq */ int irq; + /* KSI[7:0] wake-up input source configuration list */ + const struct cros_kb_raw_wuc_map_cfg *wuc_map_list; +}; + +struct cros_kb_raw_ite_data { + /* KSI[7:0] wake-up interrupt status mask */ + uint8_t ksi_pin_mask; }; static int kb_raw_ite_init(const struct device *dev) @@ -43,9 +61,17 @@ static int cros_kb_raw_ite_enable_interrupt(const struct device *dev, int enable) { const struct cros_kb_raw_ite_config *config = dev->config; + struct cros_kb_raw_ite_data *data = dev->data; if (enable) { - ECREG(IT8XXX2_WUC_WUESR3) = 0xFF; + /* + * W/C wakeup interrupt status of KSI[7:0] pins + * + * NOTE: We want to clear the status as soon as possible, + * so clear KSI[7:0] pins at a time. + */ + it8xxx2_wuc_clear_status(config->wuc_map_list[0].wucs, + data->ksi_pin_mask); ite_intc_isr_clear(config->irq); irq_enable(config->irq); } else { @@ -58,8 +84,7 @@ static int cros_kb_raw_ite_enable_interrupt(const struct device *dev, static int cros_kb_raw_ite_read_row(const struct device *dev) { const struct cros_kb_raw_ite_config *config = dev->config; - struct kscan_it8xxx2_regs *const inst = - (struct kscan_it8xxx2_regs *) config->base; + struct kscan_it8xxx2_regs *const inst = config->base; /* Bits are active-low, so invert returned levels */ return ((inst->KBS_KSI) ^ 0xff); @@ -70,8 +95,7 @@ static int cros_kb_raw_ite_drive_column(const struct device *dev, int col) int mask; unsigned int key; const struct cros_kb_raw_ite_config *config = dev->config; - struct kscan_it8xxx2_regs *const inst = - (struct kscan_it8xxx2_regs *) config->base; + struct kscan_it8xxx2_regs *const inst = config->base; /* Tri-state all outputs */ if (col == KEYBOARD_COLUMN_NONE) @@ -105,14 +129,21 @@ static int cros_kb_raw_ite_drive_column(const struct device *dev, int col) static void cros_kb_raw_ite_ksi_isr(const struct device *dev) { - ARG_UNUSED(dev); + const struct cros_kb_raw_ite_config *config = dev->config; + struct cros_kb_raw_ite_data *data = dev->data; /* * We clear IT8XXX2_IRQ_WKINTC irq status in * ite_intc_irq_handler(), after interrupt was fired. */ - /* W/C wakeup interrupt status for KSI[0-7] */ - ECREG(IT8XXX2_WUC_WUESR3) = 0xFF; + /* + * W/C wakeup interrupt status of KSI[7:0] pins + * + * NOTE: We want to clear the status as soon as possible, + * so clear KSI[7:0] pins at a time. + */ + it8xxx2_wuc_clear_status(config->wuc_map_list[0].wucs, + data->ksi_pin_mask); /* Wake-up keyboard scan task */ task_wake(TASK_ID_KEYSCAN); @@ -122,8 +153,8 @@ static int cros_kb_raw_ite_init(const struct device *dev) { unsigned int key; const struct cros_kb_raw_ite_config *config = dev->config; - struct kscan_it8xxx2_regs *const inst = - (struct kscan_it8xxx2_regs *) config->base; + struct cros_kb_raw_ite_data *data = dev->data; + struct kscan_it8xxx2_regs *const inst = config->base; /* Ensure top-level interrupt is disabled */ cros_kb_raw_ite_enable_interrupt(dev, 0); @@ -158,15 +189,38 @@ static int cros_kb_raw_ite_init(const struct device *dev) inst->KBS_KSOH1 &= ~KSOH_PIN_MASK; /* restore interrupts */ irq_unlock(key); - /* Select falling-edge triggered of wakeup interrupt for KSI[0-7] */ - ECREG(IT8XXX2_WUC_WUEMR3) = 0xFF; - /* W/C wakeup interrupt status for KSI[0-7] */ - ECREG(IT8XXX2_WUC_WUESR3) = 0xFF; + + for (int i = 0; i < KEYBOARD_KSI_PIN_COUNT; i++) { + /* Select wakeup interrupt falling-edge triggered of KSI[7:0] */ + it8xxx2_wuc_set_polarity(config->wuc_map_list[i].wucs, + config->wuc_map_list[i].mask, + WUC_TYPE_EDGE_FALLING); + /* W/C wakeup interrupt status of KSI[7:0] pins */ + it8xxx2_wuc_clear_status(config->wuc_map_list[i].wucs, + config->wuc_map_list[i].mask); + /* Enable wakeup interrupt of KSI[7:0] pins */ + it8xxx2_wuc_enable(config->wuc_map_list[i].wucs, + config->wuc_map_list[i].mask); + + /* + * We want to clear KSI[7:0] pins status at a time when wakeup + * interrupt fire, so gather the KSI[7:0] pin mask value here. + */ + if (IS_ENABLED(CONFIG_LOG)) { + if (config->wuc_map_list[i].wucs != + config->wuc_map_list[0].wucs) { + LOG_ERR("KSI%d isn't in the same wuc node!", i); + } + } + data->ksi_pin_mask |= config->wuc_map_list[i].mask; + } + + /* W/C interrupt status of KSI[7:0] pins */ ite_intc_isr_clear(config->irq); - /* Enable wakeup interrupt for KSI[0-7] */ - ECREG(IT8XXX2_WUC_WUENR3) = 0xFF; - IRQ_CONNECT(DT_INST_IRQN(0), 0, cros_kb_raw_ite_ksi_isr, NULL, 0); + irq_connect_dynamic(config->irq, 0, + (void (*)(const void *))cros_kb_raw_ite_ksi_isr, + (const void *)dev, 0); return 0; } @@ -177,12 +231,19 @@ static const struct cros_kb_raw_driver_api cros_kb_raw_ite_driver_api = { .read_rows = cros_kb_raw_ite_read_row, .enable_interrupt = cros_kb_raw_ite_enable_interrupt, }; +static const struct cros_kb_raw_wuc_map_cfg + cros_kb_raw_wuc_0[IT8XXX2_DT_INST_WUCCTRL_LEN(0)] = + IT8XXX2_DT_WUC_ITEMS_LIST(0); static const struct cros_kb_raw_ite_config cros_kb_raw_cfg = { - .base = DT_INST_REG_ADDR(0), + .base = (struct kscan_it8xxx2_regs *)DT_INST_REG_ADDR(0), .irq = DT_INST_IRQN(0), + .wuc_map_list = cros_kb_raw_wuc_0, }; -DEVICE_DT_INST_DEFINE(0, kb_raw_ite_init, NULL, NULL, &cros_kb_raw_cfg, - PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, +static struct cros_kb_raw_ite_data cros_kb_raw_data; + +DEVICE_DT_INST_DEFINE(0, kb_raw_ite_init, NULL, &cros_kb_raw_data, + &cros_kb_raw_cfg, PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &cros_kb_raw_ite_driver_api); diff --git a/zephyr/drivers/cros_system/cros_system_npcx.c b/zephyr/drivers/cros_system/cros_system_npcx.c index 038ca89ec0..879b792ee1 100644 --- a/zephyr/drivers/cros_system/cros_system_npcx.c +++ b/zephyr/drivers/cros_system/cros_system_npcx.c @@ -572,7 +572,7 @@ static const struct cros_system_driver_api cros_system_driver_npcx_api = { .chip_vendor = cros_system_npcx_get_chip_vendor, .chip_name = cros_system_npcx_get_chip_name, .chip_revision = cros_system_npcx_get_chip_revision, -#ifdef CONFIG_NPCX_PM_TRACE +#ifdef CONFIG_PM .deep_sleep_ticks = cros_system_npcx_deep_sleep_ticks, #endif }; diff --git a/zephyr/dts/bindings/battery/battery-smart.yaml b/zephyr/dts/bindings/battery/battery-smart.yaml index 8e97d010e0..c2c6d28175 100644 --- a/zephyr/dts/bindings/battery/battery-smart.yaml +++ b/zephyr/dts/bindings/battery/battery-smart.yaml @@ -13,6 +13,7 @@ properties: enum: - "aec,5477109" - "as3gwrc3ka,c235-41" + - "ganfeng,7c01" - "getac,bq40z50-R3-S3" - "getac,bq40z50-R3-S2" - "lgc,ac17a8m" diff --git a/zephyr/dts/bindings/battery/ganfeng,7c01.yaml b/zephyr/dts/bindings/battery/ganfeng,7c01.yaml new file mode 100644 index 0000000000..6601761bea --- /dev/null +++ b/zephyr/dts/bindings/battery/ganfeng,7c01.yaml @@ -0,0 +1,54 @@ +description: "Ganfeng 7C01" +compatible: "ganfeng,7c01" + +include: battery-smart.yaml + +properties: + enum-name: + type: string + default: "ganfeng,7c01" + + # Fuel gauge + manuf_name: + default: "Ganfeng" + device_name: + default: "7C01" + ship_mode_reg_addr: + default: 0x00 + ship_mode_reg_data: + default: [ 0x0010, 0x0010 ] + # Documentation: b/226820234 + fet_mfgacc_support: + default: 0 + fet_reg_addr: + default: 0x43 + fet_reg_mask: + default: 0x0001 + fet_disconnect_val: + default: 0x0000 + fet_cfet_mask: + default: 0x0002 + fet_cfet_off_val: + default: 0x0000 + + # Battery info + voltage_max: + default: 8700 + voltage_normal: + default: 7600 + voltage_min: + default: 6000 + precharge_current: + default: 256 + start_charging_min_c: + default: -20 + start_charging_max_c: + default: 60 + charging_min_c: + default: 0 + charging_max_c: + default: 60 + discharging_min_c: + default: -20 + discharging_max_c: + default: 60 diff --git a/zephyr/dts/bindings/cros_kb_raw/ite,it8xxx2-cros-kb-raw.yaml b/zephyr/dts/bindings/cros_kb_raw/ite,it8xxx2-cros-kb-raw.yaml new file mode 100644 index 0000000000..9c1d635b61 --- /dev/null +++ b/zephyr/dts/bindings/cros_kb_raw/ite,it8xxx2-cros-kb-raw.yaml @@ -0,0 +1,24 @@ +# Copyright 2022 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +description: ITE, it8xxx2-cros-kb-raw node + +compatible: "ite,it8xxx2-cros-kb-raw" + +include: cros-kb-raw-controller.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + wucctrl: + type: phandles + description: | + Configure wakeup controller, this controller is used to set that + when the interrupt is triggered in EC low power mode, it can wakeup + EC or not. Via this controller, we set the wakeup trigger edge, + enable, disable, and clear wakeup status for the specific pin which + may be gpio pins or alternate pins. diff --git a/zephyr/dts/bindings/usbc/richtek,rt9490-bc12.yaml b/zephyr/dts/bindings/usbc/richtek,rt9490-bc12.yaml index c228669fc7..94496455a3 100644 --- a/zephyr/dts/bindings/usbc/richtek,rt9490-bc12.yaml +++ b/zephyr/dts/bindings/usbc/richtek,rt9490-bc12.yaml @@ -5,3 +5,9 @@ description: USBC BC1.2 compatible: "richtek,rt9490-bc12" + +properties: + irq: + type: phandles + description: | + GPIO interrupt from BC1.2 diff --git a/zephyr/dts/bindings/vendor-prefixes.txt b/zephyr/dts/bindings/vendor-prefixes.txt index 4095b8f300..403b0ba1ea 100644 --- a/zephyr/dts/bindings/vendor-prefixes.txt +++ b/zephyr/dts/bindings/vendor-prefixes.txt @@ -14,3 +14,4 @@ smp Battery vendor aec Battery vendor powertech Battery vendor getac Battery vendor +ganfeng Battery vendor diff --git a/zephyr/include/cros/ite/it8xxx2.dtsi b/zephyr/include/cros/ite/it8xxx2.dtsi index 38224b9fd4..abb3e6bbae 100644 --- a/zephyr/include/cros/ite/it8xxx2.dtsi +++ b/zephyr/include/cros/ite/it8xxx2.dtsi @@ -78,14 +78,20 @@ label = "FLASH"; }; - /delete-node/ kscan@f01d00; - cros_kb_raw: cros-kb-raw@f01d00 { compatible = "ite,it8xxx2-cros-kb-raw"; reg = <0x00f01d00 0x29>; label = "CROS_KB_RAW_0"; interrupt-parent = <&intc>; interrupts = <13 IRQ_TYPE_LEVEL_HIGH>; + wucctrl = <&wuc_wu30 /* KSI[0] */ + &wuc_wu31 /* KSI[1] */ + &wuc_wu32 /* KSI[2] */ + &wuc_wu33 /* KSI[3] */ + &wuc_wu34 /* KSI[4] */ + &wuc_wu35 /* KSI[5] */ + &wuc_wu36 /* KSI[6] */ + &wuc_wu37>; /* KSI[7] */ status = "disabled"; }; }; diff --git a/zephyr/projects/.pylintrc b/zephyr/projects/.pylintrc new file mode 100644 index 0000000000..9ca0b5f8c9 --- /dev/null +++ b/zephyr/projects/.pylintrc @@ -0,0 +1,21 @@ +[MASTER] +init-hook='import sys; sys.path.append("/usr/lib64/python3.6/site-packages")' + +[MESSAGES CONTROL] + +disable=bad-continuation,bad-whitespace,format,fixme + +[format] + +max-line-length=88 +string-quote=double + +[BASIC] +additional-builtins= + here, + register_binman_project, + register_host_project, + register_host_test, + register_npcx_project, + register_raw_project, +good-names=BUILD diff --git a/zephyr/projects/brya/BUILD.py b/zephyr/projects/brya/BUILD.py index da7e8b1d49..ead03c459f 100644 --- a/zephyr/projects/brya/BUILD.py +++ b/zephyr/projects/brya/BUILD.py @@ -2,8 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Define zmake projects for brya.""" + def register_npcx9_variant(project_name, extra_dts_overlays=(), extra_kconfig_files=()): + """Register a variant of a brya, even though this is not named as such.""" return register_npcx_project( project_name=project_name, zephyr_board="npcx9", diff --git a/zephyr/projects/brya/prj.conf b/zephyr/projects/brya/prj.conf index f4f7569458..a824bd1b91 100644 --- a/zephyr/projects/brya/prj.conf +++ b/zephyr/projects/brya/prj.conf @@ -160,7 +160,6 @@ CONFIG_PLATFORM_EC_USB_PD_TCPM_MUX=y CONFIG_PLATFORM_EC_USB_PD_TCPM_TCPCI=y CONFIG_PLATFORM_EC_USBC_PPC_DEDICATED_INT=y CONFIG_PLATFORM_EC_USBA=y -CONFIG_PLATFORM_EC_USB_PORT_POWER_DUMB=y CONFIG_PLATFORM_EC_CONSOLE_CMD_PPC_DUMP=n CONFIG_PLATFORM_EC_CONSOLE_CMD_TCPC_DUMP=n CONFIG_PLATFORM_EC_USB_PD_TCPC_RUNTIME_CONFIG=n diff --git a/zephyr/projects/corsola/BUILD.py b/zephyr/projects/corsola/BUILD.py index af0e0edf4b..6a8ed60c09 100644 --- a/zephyr/projects/corsola/BUILD.py +++ b/zephyr/projects/corsola/BUILD.py @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Define zmake projects for corsola.""" + # Default chip is it8xxx2, some variants will use NPCX9X. @@ -11,6 +13,7 @@ def register_corsola_project( extra_dts_overlays=(), extra_kconfig_files=(), ): + """Register a variant of corsola.""" register_func = register_binman_project if chip.startswith("npcx9"): register_func = register_npcx_project diff --git a/zephyr/projects/corsola/interrupts_krabby.dts b/zephyr/projects/corsola/interrupts_krabby.dts index 2245c98c66..ddc9639d2b 100644 --- a/zephyr/projects/corsola/interrupts_krabby.dts +++ b/zephyr/projects/corsola/interrupts_krabby.dts @@ -104,7 +104,7 @@ int_usb_c1_bc12_charger: usb_c1_bc12_charger { irq-pin = <&usb_c1_bc12_charger_int_odl>; flags = <GPIO_INT_EDGE_FALLING>; - handler = "c1_bc12_interrupt"; + handler = "rt9490_bc12_dt_interrupt"; }; }; }; diff --git a/zephyr/projects/corsola/prj_kingler.conf b/zephyr/projects/corsola/prj_kingler.conf index 8cdc8f7261..fd28664a57 100644 --- a/zephyr/projects/corsola/prj_kingler.conf +++ b/zephyr/projects/corsola/prj_kingler.conf @@ -102,7 +102,6 @@ CONFIG_PLATFORM_EC_SENSOR_TIGHT_TIMESTAMPS=y # USBA CONFIG_PLATFORM_EC_USBA=y -CONFIG_PLATFORM_EC_USB_PORT_POWER_DUMB=y # USBC CONFIG_PLATFORM_EC_BC12_DETECT_PI3USB9201=y diff --git a/zephyr/projects/corsola/prj_krabby.conf b/zephyr/projects/corsola/prj_krabby.conf index ebab7ce3bd..5dd1561898 100644 --- a/zephyr/projects/corsola/prj_krabby.conf +++ b/zephyr/projects/corsola/prj_krabby.conf @@ -108,7 +108,6 @@ CONFIG_TASK_PD_STACK_SIZE=1280 # USB-A CONFIG_PLATFORM_EC_USBA=y -CONFIG_PLATFORM_EC_USB_PORT_POWER_DUMB=y # USB-C CONFIG_PLATFORM_EC_BC12_SINGLE_DRIVER=n diff --git a/zephyr/projects/corsola/src/kingler/button.c b/zephyr/projects/corsola/src/kingler/button.c index 0df87c7750..d10d771950 100644 --- a/zephyr/projects/corsola/src/kingler/button.c +++ b/zephyr/projects/corsola/src/kingler/button.c @@ -14,8 +14,9 @@ static void buttons_hook(void) { int version; - if (cbi_get_board_version(&version)) + if (cbi_get_board_version(&version)) { return; + } /* b:219891339: drop this workaround when we deprecate rev0 */ if (version == 0) { diff --git a/zephyr/projects/corsola/src/kingler/usb_pd_policy.c b/zephyr/projects/corsola/src/kingler/usb_pd_policy.c index c06f817ba1..51a05598b9 100644 --- a/zephyr/projects/corsola/src/kingler/usb_pd_policy.c +++ b/zephyr/projects/corsola/src/kingler/usb_pd_policy.c @@ -23,15 +23,17 @@ void pd_power_supply_reset(int port) prev_en = ppc_is_sourcing_vbus(port); - if (port == USBC_PORT_C1) + if (port == USBC_PORT_C1) { rt1718s_gpio_set_level(port, GPIO_EN_USB_C1_SOURCE, 0); + } /* Disable VBUS. */ ppc_vbus_source_enable(port, 0); /* Enable discharge if we were previously sourcing 5V */ - if (prev_en) + if (prev_en) { pd_set_vbus_discharge(port, 1); + } /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); @@ -44,18 +46,21 @@ int pd_set_power_supply_ready(int port) /* Disable charging. */ rv = ppc_vbus_sink_enable(port, 0); - if (rv) + if (rv) { return rv; + } pd_set_vbus_discharge(port, 0); /* Provide Vbus. */ - if (port == USBC_PORT_C1) + if (port == USBC_PORT_C1) { rt1718s_gpio_set_level(port, GPIO_EN_USB_C1_SOURCE, 1); + } rv = ppc_vbus_source_enable(port, 1); - if (rv) + if (rv) { return rv; + } /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); diff --git a/zephyr/projects/corsola/src/kingler/usbc_config.c b/zephyr/projects/corsola/src/kingler/usbc_config.c index 0fd22c0dba..bcb1bf70d5 100644 --- a/zephyr/projects/corsola/src/kingler/usbc_config.c +++ b/zephyr/projects/corsola/src/kingler/usbc_config.c @@ -150,9 +150,10 @@ void board_tcpc_init(void) /* Enable TCPC interrupts */ gpio_enable_dt_interrupt(GPIO_INT_FROM_NODELABEL(int_usb_c0_tcpc)); - if (corsola_get_db_type() == CORSOLA_DB_TYPEC) + if (corsola_get_db_type() == CORSOLA_DB_TYPEC) { gpio_enable_dt_interrupt( GPIO_INT_FROM_NODELABEL(int_usb_c1_tcpc)); + } /* Enable BC1.2 interrupts. */ gpio_enable_dt_interrupt(GPIO_INT_FROM_NODELABEL(int_usb_c0_bc12)); @@ -161,9 +162,10 @@ void board_tcpc_init(void) * Initialize HPD to low; after sysjump SOC needs to see * HPD pulse to enable video path */ - for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) + for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) { usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | USB_PD_MUX_HPD_IRQ_DEASSERTED); + } } DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_POST_I2C); @@ -230,8 +232,9 @@ int board_vbus_source_enabled(int port) __override int board_rt1718s_set_snk_enable(int port, int enable) { - if (port == USBC_PORT_C1) + if (port == USBC_PORT_C1) { rt1718s_gpio_set_level(port, GPIO_EN_USB_C1_SINK, enable); + } return EC_SUCCESS; } @@ -242,8 +245,9 @@ int board_set_active_charge_port(int port) bool is_valid_port = (port >= 0 && port < board_get_usb_pd_port_count()); - if (!is_valid_port && port != CHARGE_PORT_NONE) + if (!is_valid_port && port != CHARGE_PORT_NONE) { return EC_ERROR_INVAL; + } if (port == CHARGE_PORT_NONE) { CPRINTS("Disabling all charger ports"); @@ -254,8 +258,9 @@ int board_set_active_charge_port(int port) * Do not return early if one fails otherwise we can * get into a boot loop assertion failure. */ - if (ppc_vbus_sink_enable(i, 0)) + if (ppc_vbus_sink_enable(i, 0)) { CPRINTS("Disabling C%d as sink failed.", i); + } } return EC_SUCCESS; @@ -274,11 +279,13 @@ int board_set_active_charge_port(int port) * requested charge port. */ for (i = 0; i < board_get_usb_pd_port_count(); i++) { - if (i == port) + if (i == port) { continue; + } - if (ppc_vbus_sink_enable(i, 0)) + if (ppc_vbus_sink_enable(i, 0)) { CPRINTS("C%d: sink path disable failed.", i); + } } /* Enable requested charge port. */ @@ -297,12 +304,15 @@ uint16_t tcpc_get_alert_status(void) if (!gpio_pin_get_dt( GPIO_DT_FROM_NODELABEL(gpio_usb_c0_tcpc_int_odl))) { if (!gpio_pin_get_dt( - GPIO_DT_FROM_NODELABEL(gpio_usb_c0_tcpc_rst))) + GPIO_DT_FROM_NODELABEL(gpio_usb_c0_tcpc_rst))) { status |= PD_STATUS_TCPC_ALERT_0; + } } - if (!gpio_pin_get_dt(GPIO_DT_FROM_NODELABEL(gpio_usb_c1_tcpc_int_odl))) + if (!gpio_pin_get_dt( + GPIO_DT_FROM_NODELABEL(gpio_usb_c1_tcpc_int_odl))) { return status |= PD_STATUS_TCPC_ALERT_1; + } return status; } diff --git a/zephyr/projects/corsola/src/krabby/charger_workaround.c b/zephyr/projects/corsola/src/krabby/charger_workaround.c index 48cd541146..26bfac1bea 100644 --- a/zephyr/projects/corsola/src/krabby/charger_workaround.c +++ b/zephyr/projects/corsola/src/krabby/charger_workaround.c @@ -22,8 +22,9 @@ static void enter_hidden_mode(void) /* b/194967754#comment5: work around for IBUS ADC unstable issue */ static void ibus_adc_workaround(void) { - if (system_get_board_version() != 0) + if (system_get_board_version() != 0) { return; + } i2c_update8(chg_chips[CHARGER_SOLO].i2c_port, chg_chips[CHARGER_SOLO].i2c_addr_flags, diff --git a/zephyr/projects/corsola/src/krabby/hooks.c b/zephyr/projects/corsola/src/krabby/hooks.c index 70f3efe8e1..e91993be10 100644 --- a/zephyr/projects/corsola/src/krabby/hooks.c +++ b/zephyr/projects/corsola/src/krabby/hooks.c @@ -7,6 +7,9 @@ #include <drivers/gpio.h> #include <ap_power/ap_power.h> +#include "charger.h" +#include "driver/charger/rt9490.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" @@ -22,10 +25,11 @@ static void board_i2c3_ctrl(bool enable) (struct gctrl_it8xxx2_regs *) DT_REG_ADDR(DT_NODELABEL(gctrl)); - if (enable) + if (enable) { gctrl_base->GCTRL_PMER3 |= IT8XXX2_GCTRL_SMB3PSEL; - else + } else { gctrl_base->GCTRL_PMER3 &= ~IT8XXX2_GCTRL_SMB3PSEL; + } } } @@ -75,3 +79,12 @@ static int install_suspend_handler(const struct device *unused) } SYS_INIT(install_suspend_handler, APPLICATION, 1); + +static void board_hook_ac_change(void) +{ + if (system_get_board_version() >= 1) { + rt9490_enable_adc(CHARGER_SOLO, extpower_is_present()); + } +} +DECLARE_HOOK(HOOK_AC_CHANGE, board_hook_ac_change, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, board_hook_ac_change, HOOK_PRIO_LAST); diff --git a/zephyr/projects/corsola/src/krabby/led.c b/zephyr/projects/corsola/src/krabby/led.c index 812d693626..8e2cf10cd9 100644 --- a/zephyr/projects/corsola/src/krabby/led.c +++ b/zephyr/projects/corsola/src/krabby/led.c @@ -128,17 +128,19 @@ void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) { if (led_id == EC_LED_ID_BATTERY_LED) { - if (brightness[EC_LED_COLOR_AMBER] != 0) + if (brightness[EC_LED_COLOR_AMBER] != 0) { led_set_color_battery(EC_LED_COLOR_AMBER); - else if (brightness[EC_LED_COLOR_WHITE] != 0) + } else if (brightness[EC_LED_COLOR_WHITE] != 0) { led_set_color_battery(EC_LED_COLOR_WHITE); - else + } else { led_set_color_battery(LED_OFF); + } } else if (led_id == EC_LED_ID_POWER_LED) { - if (brightness[EC_LED_COLOR_WHITE] != 0) + if (brightness[EC_LED_COLOR_WHITE] != 0) { led_set_color_power(EC_LED_COLOR_WHITE); - else + } else { led_set_color_power(LED_OFF); + } } return EC_SUCCESS; diff --git a/zephyr/projects/corsola/src/krabby/usb_pd_policy.c b/zephyr/projects/corsola/src/krabby/usb_pd_policy.c index fbdeda89bc..5f9ae83a19 100644 --- a/zephyr/projects/corsola/src/krabby/usb_pd_policy.c +++ b/zephyr/projects/corsola/src/krabby/usb_pd_policy.c @@ -27,13 +27,15 @@ int pd_snk_is_vbus_provided(int port) * There's no PPC to inform VBUS change for usb_charger, so inform * the usb_charger now. */ - if (!!(vbus_prev[port] != vbus)) + if (!!(vbus_prev[port] != vbus)) { usb_charger_vbus_change(port, vbus); + } - if (vbus) + if (vbus) { atomic_or(&vbus_prev[port], 1); - else + } else { atomic_clear(&vbus_prev[port]); + } #endif return vbus; } @@ -48,8 +50,9 @@ void pd_power_supply_reset(int port) ppc_vbus_source_enable(port, 0); /* Enable discharge if we were previously sourcing 5V */ - if (prev_en) + if (prev_en) { pd_set_vbus_discharge(port, 1); + } /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); @@ -61,15 +64,17 @@ int pd_set_power_supply_ready(int port) /* Disable charging. */ rv = ppc_vbus_sink_enable(port, 0); - if (rv) + if (rv) { return rv; + } pd_set_vbus_discharge(port, 0); /* Provide Vbus. */ rv = ppc_vbus_source_enable(port, 1); - if (rv) + if (rv) { return rv; + } /* Notify host of power info change. */ pd_send_host_event(PD_EVENT_POWER_CHANGE); diff --git a/zephyr/projects/corsola/src/krabby/usbc_config.c b/zephyr/projects/corsola/src/krabby/usbc_config.c index b46a9edf8f..7ba0ca9e50 100644 --- a/zephyr/projects/corsola/src/krabby/usbc_config.c +++ b/zephyr/projects/corsola/src/krabby/usbc_config.c @@ -41,20 +41,12 @@ void c0_bc12_interrupt(enum gpio_signal signal) rt1739_interrupt(0); } -void c1_bc12_interrupt(enum gpio_signal signal) -{ - rt9490_interrupt(1); -} - - static void board_sub_bc12_init(void) { - if (corsola_get_db_type() == CORSOLA_DB_TYPEC) - gpio_enable_dt_interrupt( - GPIO_INT_FROM_NODELABEL(int_usb_c1_bc12_charger)); - else + if (corsola_get_db_type() == CORSOLA_DB_HDMI) { /* If this is not a Type-C subboard, disable the task. */ task_disable_task(TASK_ID_USB_CHG_P1); + } } /* Must be done after I2C and subboard */ DECLARE_HOOK(HOOK_INIT, board_sub_bc12_init, HOOK_PRIO_POST_I2C); @@ -67,18 +59,21 @@ DECLARE_HOOK(HOOK_INIT, board_usbc_init, HOOK_PRIO_POST_DEFAULT); void ppc_interrupt(enum gpio_signal signal) { - if (signal == GPIO_SIGNAL(DT_ALIAS(gpio_usb_c1_ppc_int_odl))) + if (signal == GPIO_SIGNAL(DT_ALIAS(gpio_usb_c1_ppc_int_odl))) { syv682x_interrupt(1); + } } int ppc_get_alert_status(int port) { - if (port == 0) + if (port == 0) { return gpio_pin_get_dt( GPIO_DT_FROM_NODELABEL(usb_c0_ppc_bc12_int_odl)) == 0; - if (port == 1 && corsola_get_db_type() == CORSOLA_DB_TYPEC) + } + if (port == 1 && corsola_get_db_type() == CORSOLA_DB_TYPEC) { return gpio_pin_get_dt( GPIO_DT_FROM_ALIAS(gpio_usb_c1_ppc_int_odl)) == 0; + } return 0; } @@ -127,8 +122,9 @@ int board_set_active_charge_port(int port) int i; int is_valid_port = (port >= 0 && port < board_get_usb_pd_port_count()); - if (!is_valid_port && port != CHARGE_PORT_NONE) + if (!is_valid_port && port != CHARGE_PORT_NONE) { return EC_ERROR_INVAL; + } if (port == CHARGE_PORT_NONE) { CPRINTS("Disabling all charger ports"); @@ -139,8 +135,9 @@ int board_set_active_charge_port(int port) * Do not return early if one fails otherwise we can * get into a boot loop assertion failure. */ - if (ppc_vbus_sink_enable(i, 0)) + if (ppc_vbus_sink_enable(i, 0)) { CPRINTS("Disabling C%d as sink failed.", i); + } } return EC_SUCCESS; @@ -159,11 +156,13 @@ int board_set_active_charge_port(int port) * requested charge port. */ for (i = 0; i < ppc_cnt; i++) { - if (i == port) + if (i == port) { continue; + } - if (ppc_vbus_sink_enable(i, 0)) + if (ppc_vbus_sink_enable(i, 0)) { CPRINTS("C%d: sink path disable failed.", i); + } } /* Enable requested charge port. */ @@ -207,10 +206,12 @@ struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { #ifdef CONFIG_USB_PD_VBUS_MEASURE_ADC_EACH_PORT enum adc_channel board_get_vbus_adc(int port) { - if (port == 0) + if (port == 0) { return ADC_VBUS_C0; - if (port == 1) + } + if (port == 1) { return ADC_VBUS_C1; + } CPRINTSUSB("Unknown vbus adc port id: %d", port); return ADC_VBUS_C0; } diff --git a/zephyr/projects/corsola/src/usb_pd_policy.c b/zephyr/projects/corsola/src/usb_pd_policy.c index c8169e3877..f8795143ee 100644 --- a/zephyr/projects/corsola/src/usb_pd_policy.c +++ b/zephyr/projects/corsola/src/usb_pd_policy.c @@ -69,8 +69,9 @@ __override int svdm_dp_config(int port, uint32_t *payload) mux_state_t mux_mode = svdm_dp_get_mux_mode(port); int mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]); - if (!pin_mode) + if (!pin_mode) { return 0; + } CPRINTS("pin_mode: %x, mf: %d, mux: %d", pin_mode, mf_pref, mux_mode); /* @@ -102,8 +103,9 @@ int corsola_is_dp_muxable(int port) for (i = 0; i < board_get_usb_pd_port_count(); i++) { if (i != port) { - if (usb_mux_get(i) & USB_PD_MUX_DP_ENABLED) + if (usb_mux_get(i) & USB_PD_MUX_DP_ENABLED) { return 0; + } } } @@ -140,18 +142,21 @@ __override int svdm_dp_attention(int port, uint32_t *payload) } if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && - (irq || lvl)) + (irq || lvl)) { /* * Wake up the AP. IRQ or level high indicates a DP sink is now * present. */ - if (IS_ENABLED(CONFIG_MKBP_EVENT)) + if (IS_ENABLED(CONFIG_MKBP_EVENT)) { pd_notify_dp_alt_mode_entry(port); + } + } /* Its initial DP status message prior to config */ if (!(dp_flags[port] & DP_FLAGS_DP_ON)) { - if (lvl) + if (lvl) { dp_flags[port] |= DP_FLAGS_HPD_HI_PENDING; + } return 1; } @@ -168,8 +173,9 @@ __override int svdm_dp_attention(int port, uint32_t *payload) if (irq && cur_lvl) { uint64_t now = get_time().val; /* wait for the minimum spacing between IRQ_HPD if needed */ - if (now < svdm_hpd_deadline[port]) + if (now < svdm_hpd_deadline[port]) { usleep(svdm_hpd_deadline[port] - now); + } /* generate IRQ_HPD pulse */ svdm_set_hpd_gpio(port, 0); @@ -193,8 +199,9 @@ __override int svdm_dp_attention(int port, uint32_t *payload) usb_mux_hpd_update(port, mux_state); #ifdef USB_PD_PORT_TCPC_MST - if (port == USB_PD_PORT_TCPC_MST) + if (port == USB_PD_PORT_TCPC_MST) { baseboard_mst_enable_control(port, lvl); + } #endif /* ack */ diff --git a/zephyr/projects/corsola/src/usbc_config.c b/zephyr/projects/corsola/src/usbc_config.c index 54e5f48b25..5506e7fbe9 100644 --- a/zephyr/projects/corsola/src/usbc_config.c +++ b/zephyr/projects/corsola/src/usbc_config.c @@ -54,10 +54,11 @@ DECLARE_HOOK(HOOK_INIT, baseboard_init, HOOK_PRIO_PRE_DEFAULT); __override uint8_t board_get_usb_pd_port_count(void) { if (corsola_get_db_type() == CORSOLA_DB_HDMI) { - if (tasks_inited) + if (tasks_inited) { return CONFIG_USB_PD_PORT_MAX_COUNT; - else + } else { return CONFIG_USB_PD_PORT_MAX_COUNT - 1; + } } return CONFIG_USB_PD_PORT_MAX_COUNT; @@ -70,8 +71,9 @@ void usb_a0_interrupt(enum gpio_signal signal) GPIO_DT_FROM_NODELABEL(gpio_ap_xhci_init_done)) ? USB_CHARGE_MODE_ENABLED : USB_CHARGE_MODE_DISABLED; - for (int i = 0; i < USB_PORT_COUNT; i++) + for (int i = 0; i < USB_PORT_COUNT; i++) { usb_charge_set_mode(i, mode, USB_ALLOW_SUSPEND_CHARGE); + } /* * Trigger hard reset to cycle Vbus on Type-C ports, recommended by @@ -79,8 +81,9 @@ void usb_a0_interrupt(enum gpio_signal signal) */ if (gpio_get_level(signal)) { for (int i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { - if (tc_is_attached_src(i)) + if (tc_is_attached_src(i)) { pd_dpm_request(i, DPM_REQUEST_HARD_RESET_SEND); + } } } } @@ -112,14 +115,16 @@ static void ps185_hdmi_hpd_deferred(void) GPIO_DT_FROM_ALIAS(gpio_ps185_ec_dp_hpd)); /* HPD status not changed, probably a glitch, just return. */ - if (debounced_hpd == new_hpd) + if (debounced_hpd == new_hpd) { return; + } debounced_hpd = new_hpd; if (!corsola_is_dp_muxable(USBC_PORT_C1)) { - if (debounced_hpd) + if (debounced_hpd) { CPRINTS("C0 port is already muxed."); + } return; } @@ -178,12 +183,13 @@ static void hdmi_hpd_interrupt(enum gpio_signal signal) { hook_call_deferred(&ps185_hdmi_hpd_deferred_data, PS185_HPD_DEBOUCE); - if (!gpio_pin_get_dt(GPIO_DT_FROM_ALIAS(gpio_ps185_ec_dp_hpd))) + if (!gpio_pin_get_dt(GPIO_DT_FROM_ALIAS(gpio_ps185_ec_dp_hpd))) { hook_call_deferred(&ps185_hdmi_hpd_disconnect_deferred_data, HPD_SINK_ABSENCE_DEBOUNCE); - else + } else { hook_call_deferred(&ps185_hdmi_hpd_disconnect_deferred_data, -1); + } } /* HDMI/TYPE-C function shared subboard interrupt */ @@ -191,13 +197,14 @@ void x_ec_interrupt(enum gpio_signal signal) { int sub = corsola_get_db_type(); - if (sub == CORSOLA_DB_TYPEC) + if (sub == CORSOLA_DB_TYPEC) { /* C1: PPC interrupt */ ppc_interrupt(signal); - else if (sub == CORSOLA_DB_HDMI) + } else if (sub == CORSOLA_DB_HDMI) { hdmi_hpd_interrupt(signal); - else + } else { CPRINTS("Undetected subboard interrupt."); + } } static void board_hdmi_handler(struct ap_power_ev_callback *cb, @@ -278,10 +285,11 @@ DECLARE_HOOK(HOOK_INIT, baseboard_x_ec_gpio2_init, HOOK_PRIO_DEFAULT); __override uint8_t get_dp_pin_mode(int port) { if (corsola_get_db_type() == CORSOLA_DB_HDMI && port == USBC_PORT_C1) { - if (usb_mux_get(USBC_PORT_C1) & USB_PD_MUX_DP_ENABLED) + if (usb_mux_get(USBC_PORT_C1) & USB_PD_MUX_DP_ENABLED) { return MODE_DP_PIN_E; - else + } else { return 0; + } } return pd_dfp_dp_get_pin_mode(port, dp_status[port]); diff --git a/zephyr/projects/corsola/src/variant_db_detection.c b/zephyr/projects/corsola/src/variant_db_detection.c index 89741cce18..fc8427fbc7 100644 --- a/zephyr/projects/corsola/src/variant_db_detection.c +++ b/zephyr/projects/corsola/src/variant_db_detection.c @@ -55,13 +55,15 @@ enum corsola_db_type corsola_get_db_type(void) { static enum corsola_db_type db = CORSOLA_DB_NONE; - if (db != CORSOLA_DB_NONE) + if (db != CORSOLA_DB_NONE) { return db; + } - if (!gpio_pin_get_dt(GPIO_DT_FROM_NODELABEL(gpio_hdmi_prsnt_odl))) + if (!gpio_pin_get_dt(GPIO_DT_FROM_NODELABEL(gpio_hdmi_prsnt_odl))) { db = CORSOLA_DB_HDMI; - else + } else { db = CORSOLA_DB_TYPEC; + } corsola_db_config(db); diff --git a/zephyr/projects/corsola/usbc_krabby.dts b/zephyr/projects/corsola/usbc_krabby.dts index 7ee4d2b8a5..8970ebc845 100644 --- a/zephyr/projects/corsola/usbc_krabby.dts +++ b/zephyr/projects/corsola/usbc_krabby.dts @@ -32,6 +32,7 @@ bc12 { compatible = "richtek,rt9490-bc12"; status = "okay"; + irq = <&int_usb_c1_bc12_charger>; }; ppc { compatible = "silergy,syv682x"; diff --git a/zephyr/projects/herobrine/BUILD.py b/zephyr/projects/herobrine/BUILD.py index f2c86014ab..3bf790e0a7 100644 --- a/zephyr/projects/herobrine/BUILD.py +++ b/zephyr/projects/herobrine/BUILD.py @@ -2,8 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Define zmake projects for herobrine.""" + def register_variant(project_name, extra_dts_overlays=(), extra_kconfig_files=()): + """Register a variant of herobrine.""" register_npcx_project( project_name=project_name, zephyr_board="npcx9", @@ -43,7 +46,7 @@ register_variant( register_variant( project_name="hoglin", extra_dts_overlays=[ - here / "battery_herobrine.dts", + here / "battery_hoglin.dts", here / "gpio_hoglin.dts", here / "motionsense_hoglin.dts", here / "switchcap_hoglin.dts", diff --git a/zephyr/projects/herobrine/battery_hoglin.dts b/zephyr/projects/herobrine/battery_hoglin.dts new file mode 100644 index 0000000000..79fc6ca296 --- /dev/null +++ b/zephyr/projects/herobrine/battery_hoglin.dts @@ -0,0 +1,12 @@ +/* Copyright 2022 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. + */ + +/ { + batteries { + default_battery: 7c01 { + compatible = "ganfeng,7c01", "battery-smart"; + }; + }; +}; diff --git a/zephyr/projects/herobrine/prj.conf b/zephyr/projects/herobrine/prj.conf index 99d2d8c067..d61a8f7d32 100644 --- a/zephyr/projects/herobrine/prj.conf +++ b/zephyr/projects/herobrine/prj.conf @@ -100,7 +100,6 @@ CONFIG_PLATFORM_EC_CONSOLE_CMD_CHARGER_ADC_AMON_BMON=y # USB-A CONFIG_PLATFORM_EC_USBA=y -CONFIG_PLATFORM_EC_USB_PORT_POWER_DUMB=y # USB-C CONFIG_PLATFORM_EC_USB_PD_FRS=y @@ -122,7 +121,6 @@ CONFIG_PLATFORM_EC_USB_PD_TCPM_PS8805=y CONFIG_PLATFORM_EC_USB_PD_TCPC_RUNTIME_CONFIG=n CONFIG_PLATFORM_EC_USB_MUX_RUNTIME_CONFIG=n CONFIG_PLATFORM_EC_USB_PD_LOGGING=y -CONFIG_PLATFORM_EC_USB_PORT_POWER_DUMB=y CONFIG_PLATFORM_EC_CONFIG_USB_PD_3A_PORTS=2 # USB ID diff --git a/zephyr/projects/intelrvp/BUILD.py b/zephyr/projects/intelrvp/BUILD.py index 89ddd46970..1d052f2b55 100644 --- a/zephyr/projects/intelrvp/BUILD.py +++ b/zephyr/projects/intelrvp/BUILD.py @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Define zmake projects for intelrvp.""" + # intelrvp has adlrvp_npcx, adlrvpp_ite, adlrvpp_mchp etc @@ -11,6 +13,7 @@ def register_intelrvp_project( extra_dts_overlays=(), extra_kconfig_files=(), ): + """Register a variant of intelrvp.""" register_func = register_binman_project if chip.startswith("npcx9"): register_func = register_npcx_project diff --git a/zephyr/projects/intelrvp/mtlrvp/mtlrvpp_npcx/gpio.dts b/zephyr/projects/intelrvp/mtlrvp/mtlrvpp_npcx/gpio.dts index fc2a7448c3..fbe42b2303 100644 --- a/zephyr/projects/intelrvp/mtlrvp/mtlrvpp_npcx/gpio.dts +++ b/zephyr/projects/intelrvp/mtlrvp/mtlrvpp_npcx/gpio.dts @@ -258,6 +258,28 @@ tp-gpiof4 { gpios = <&gpiof 4 GPIO_INPUT>; }; + /* USB C IOEX configuration */ + usb-c0-hbr-ls-en { + gpios = <&ioex_c0 2 GPIO_OUTPUT_LOW>; + }; + usb-c0-hbr-rst { + gpios = <&ioex_c0 3 GPIO_OUTPUT_LOW>; + }; + usb-c1-hbr-ls-en { + gpios = <&ioex_c1 2 GPIO_OUTPUT_LOW>; + }; + usb-c1-hbr-rst { + gpios = <&ioex_c1 3 GPIO_OUTPUT_LOW>; + }; + usb-c0-mux-oe-n { + gpios = <&ioex_c0 4 GPIO_OUTPUT_LOW>; + }; + usb-c0-mux-sbu-sel-0 { + gpios = <&ioex_c0 6 GPIO_OUTPUT_HIGH>; + }; + usb-c0-mux-sbu-sel-1 { + gpios = <&ioex_c1 4 GPIO_OUTPUT_LOW>; + }; }; def-lvol-io-list { @@ -274,3 +296,43 @@ >; }; }; + +&i2c0_0 { + nct38xx_C0:nct38xx_C0@70 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nuvoton,nct38xx-gpio"; + reg = <0x70>; + label = "NCT38XX_C0"; + + ioex_c0:gpio@0 { + compatible = "nuvoton,nct38xx-gpio-port"; + reg = <0x0>; + label = "NCT38XX_C0_GPIO0"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + pin_mask = <0xff>; + pinmux_mask = <0xf7>; + }; + }; + + nct38xx_C1:nct38xx_C1@70 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nuvoton,nct38xx-gpio"; + reg = <0x70>; + label = "NCT38XX_C1"; + + ioex_c1:gpio@0 { + compatible = "nuvoton,nct38xx-gpio-port"; + reg = <0x0>; + label = "NCT38XX_C1_GPIO0"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + pin_mask = <0xff>; + pinmux_mask = <0xf7>; + }; + }; +}; diff --git a/zephyr/projects/intelrvp/mtlrvp/mtlrvpp_npcx/mtlrvp_npcx.dts b/zephyr/projects/intelrvp/mtlrvp/mtlrvpp_npcx/mtlrvp_npcx.dts index e50330c6d4..9bddcb88ec 100644 --- a/zephyr/projects/intelrvp/mtlrvp/mtlrvpp_npcx/mtlrvp_npcx.dts +++ b/zephyr/projects/intelrvp/mtlrvp/mtlrvpp_npcx/mtlrvp_npcx.dts @@ -15,11 +15,11 @@ i2c-port = <&i2c7_0>; enum-name = "I2C_PORT_CHARGER"; }; - typec_aic1 { + typec_aic1: typec-aic1{ i2c-port = <&i2c0_0>; enum-name = "I2C_PORT_TYPEC_AIC_1"; }; - typec_aic2 { + typec_aic2: typec-aic2{ i2c-port = <&i2c2_0>; enum-name = "I2C_PORT_TYPEC_AIC_2"; }; diff --git a/zephyr/projects/intelrvp/mtlrvp/prj.conf b/zephyr/projects/intelrvp/mtlrvp/prj.conf index fde700735e..badcb562ec 100644 --- a/zephyr/projects/intelrvp/mtlrvp/prj.conf +++ b/zephyr/projects/intelrvp/mtlrvp/prj.conf @@ -18,7 +18,13 @@ CONFIG_PLATFORM_EC_USBC=n CONFIG_PLATFORM_EC_CHARGER=n # IOEX +CONFIG_PLATFORM_EC_IOEX=y CONFIG_GPIO_PCA95XX=y +CONFIG_GPIO_NCT38XX=y + +# USB CONFIG +CONFIG_PLATFORM_EC_USB_PD_TCPM_NCT38XX=y +CONFIG_PLATFORM_EC_USB_PD_TCPM_MUX=y # TODO: Enable these in follow on CLs CONFIG_PLATFORM_EC_KEYBOARD=n diff --git a/zephyr/projects/it8xxx2_evb/BUILD.py b/zephyr/projects/it8xxx2_evb/BUILD.py index 9d488776be..3dea4d9c20 100644 --- a/zephyr/projects/it8xxx2_evb/BUILD.py +++ b/zephyr/projects/it8xxx2_evb/BUILD.py @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Define zmake projects for it8xxx2_evb.""" + register_raw_project( project_name="it8xxx2_evb", zephyr_board="it8xxx2_evb", diff --git a/zephyr/projects/nissa/BUILD.py b/zephyr/projects/nissa/BUILD.py index 618b6401b1..6b8cc39dbf 100644 --- a/zephyr/projects/nissa/BUILD.py +++ b/zephyr/projects/nissa/BUILD.py @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Define zmake projects for nissa.""" + # Nivviks has NPCX993F, Nereid has ITE81302 @@ -11,6 +13,7 @@ def register_nissa_project( extra_dts_overlays=(), extra_kconfig_files=(), ): + """Register a variant of nissa.""" register_func = register_binman_project if chip.startswith("npcx9"): register_func = register_npcx_project diff --git a/zephyr/projects/nissa/nereid_overlay.dts b/zephyr/projects/nissa/nereid_overlay.dts index 534f9ff010..08b796d0fe 100644 --- a/zephyr/projects/nissa/nereid_overlay.dts +++ b/zephyr/projects/nissa/nereid_overlay.dts @@ -127,6 +127,10 @@ gpio-en-rails-odl = &gpio_sb_1; gpio-hdmi-en-odl = &gpio_sb_4; gpio-hpd-odl = &gpio_sb_3; + /* + * Enable S5 rails for LTE sub-board + */ + gpio-en-sub-s5-rails = &gpio_sb_2; }; named-temp-sensors { diff --git a/zephyr/projects/nissa/nivviks_overlay.dts b/zephyr/projects/nissa/nivviks_overlay.dts index ab34f1c985..63c857cf6d 100644 --- a/zephyr/projects/nissa/nivviks_overlay.dts +++ b/zephyr/projects/nissa/nivviks_overlay.dts @@ -126,6 +126,10 @@ */ gpio-hdmi-en-odl = &gpio_sb_3; gpio-hpd-odl = &gpio_sb_4; + /* + * Enable S5 rails for LTE sub-board + */ + gpio-en-sub-s5-rails = &gpio_sb_2; }; named-temp-sensors { diff --git a/zephyr/projects/nissa/prj.conf b/zephyr/projects/nissa/prj.conf index 7ba18ccc6d..6e870398a6 100644 --- a/zephyr/projects/nissa/prj.conf +++ b/zephyr/projects/nissa/prj.conf @@ -140,6 +140,7 @@ CONFIG_PLATFORM_EC_BATTERY_CUT_OFF=y CONFIG_PLATFORM_EC_BATTERY_PRESENT_GPIO=y CONFIG_PLATFORM_EC_BATTERY_FUEL_GAUGE=y CONFIG_PLATFORM_EC_BATTERY_SMART=y +CONFIG_PLATFORM_EC_BATTERY_REVIVE_DISCONNECT=y # Charger support CONFIG_PLATFORM_EC_CHARGER=y diff --git a/zephyr/projects/nissa/src/sub_board.c b/zephyr/projects/nissa/src/sub_board.c index a42e0c3b64..7dd5a6208d 100644 --- a/zephyr/projects/nissa/src/sub_board.c +++ b/zephyr/projects/nissa/src/sub_board.c @@ -69,6 +69,27 @@ static void hdmi_hpd_interrupt(const struct device *device, LOG_DBG("HDMI HPD changed state to %d", state); } +static void lte_power_handler(struct ap_power_ev_callback *cb, + struct ap_power_ev_data data) +{ + /* Enable rails for S5 */ + const struct gpio_dt_spec *s5_rail = + GPIO_DT_FROM_ALIAS(gpio_en_sub_s5_rails); + switch (data.event) { + case AP_POWER_PRE_INIT: + LOG_DBG("Enabling LTE sub-board power rails"); + gpio_pin_set_dt(s5_rail, 1); + break; + case AP_POWER_SHUTDOWN: + LOG_DBG("Disabling LTE sub-board power rails"); + gpio_pin_set_dt(s5_rail, 0); + break; + default: + LOG_ERR("Unhandled LTE power event %d", data.event); + break; + } +} + /** * Configure GPIOs (and other pin functions) that vary with present sub-board. * @@ -79,6 +100,7 @@ static void hdmi_hpd_interrupt(const struct device *device, static void nereid_subboard_config(void) { enum nissa_sub_board_type sb = nissa_get_sb_type(); + static struct ap_power_ev_callback power_cb; /* * USB-A port: current limit output is configured by default and unused @@ -114,15 +136,16 @@ static void nereid_subboard_config(void) /* Disable the port 1 charger task */ task_disable_task(TASK_ID_USB_CHG_P1); } - /* - * HDMI: two outputs control power which must be configured to - * non-default settings, and HPD must be forwarded to the AP on - * another output pin. - */ - if (sb == NISSA_SB_HDMI_A) { + + switch (sb) { + case NISSA_SB_HDMI_A: + /* + * HDMI: two outputs control power which must be configured to + * non-default settings, and HPD must be forwarded to the AP + * on another output pin. + */ const struct gpio_dt_spec *hpd_gpio = GPIO_DT_FROM_ALIAS(gpio_hpd_odl); - static struct ap_power_ev_callback hdmi_power_cb; static struct gpio_callback hdmi_hpd_cb; int rv, irq_key; @@ -135,10 +158,10 @@ static void nereid_subboard_config(void) GPIO_ACTIVE_LOW); /* Control HDMI power in concert with AP */ ap_power_ev_init_callback( - &hdmi_power_cb, hdmi_power_handler, + &power_cb, hdmi_power_handler, AP_POWER_PRE_INIT | AP_POWER_HARD_OFF | AP_POWER_STARTUP | AP_POWER_SHUTDOWN); - ap_power_ev_add_callback(&hdmi_power_cb); + ap_power_ev_add_callback(&power_cb); /* * Configure HPD input from sub-board; it's inverted by a buffer @@ -163,6 +186,26 @@ static void nereid_subboard_config(void) hdmi_hpd_interrupt(hpd_gpio->port, &hdmi_hpd_cb, BIT(hpd_gpio->pin)); irq_unlock(irq_key); + break; + + case NISSA_SB_C_LTE: + /* + * LTE: Set up callbacks for enabling/disabling + * sub-board power on S5 state. + */ + gpio_pin_configure_dt(GPIO_DT_FROM_ALIAS(gpio_en_sub_s5_rails), + GPIO_OUTPUT_INACTIVE); + /* Control LTE power when CPU entering or + * exiting S5 state. + */ + ap_power_ev_init_callback( + &power_cb, lte_power_handler, + AP_POWER_SHUTDOWN | AP_POWER_PRE_INIT); + ap_power_ev_add_callback(&power_cb); + break; + + default: + break; } } DECLARE_HOOK(HOOK_INIT, nereid_subboard_config, HOOK_PRIO_POST_FIRST); diff --git a/zephyr/projects/npcx_evb/npcx7/BUILD.py b/zephyr/projects/npcx_evb/npcx7/BUILD.py index a8e671609c..89afed0fc1 100644 --- a/zephyr/projects/npcx_evb/npcx7/BUILD.py +++ b/zephyr/projects/npcx_evb/npcx7/BUILD.py @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Define zmake projects for npcx7_evb.""" + register_npcx_project( project_name="npcx7", zephyr_board="npcx7_evb", diff --git a/zephyr/projects/npcx_evb/npcx7/prj.conf b/zephyr/projects/npcx_evb/npcx7/prj.conf index 2e8fa83cf8..0b858a3a82 100644 --- a/zephyr/projects/npcx_evb/npcx7/prj.conf +++ b/zephyr/projects/npcx_evb/npcx7/prj.conf @@ -54,7 +54,4 @@ CONFIG_LOG=y # Avoid underflow info from tachometer CONFIG_SENSOR_LOG_LEVEL_ERR=y -# Avoid info storm from power management -CONFIG_SOC_LOG_LEVEL_ERR=y - CONFIG_SYSCON=y diff --git a/zephyr/projects/npcx_evb/npcx9/BUILD.py b/zephyr/projects/npcx_evb/npcx9/BUILD.py index fb1b2707d8..efd96c9020 100644 --- a/zephyr/projects/npcx_evb/npcx9/BUILD.py +++ b/zephyr/projects/npcx_evb/npcx9/BUILD.py @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Define zmake projects for npcx9_evb.""" + register_npcx_project( project_name="npcx9", zephyr_board="npcx9_evb", diff --git a/zephyr/projects/npcx_evb/npcx9/prj.conf b/zephyr/projects/npcx_evb/npcx9/prj.conf index c025e32ec5..becb9ed228 100644 --- a/zephyr/projects/npcx_evb/npcx9/prj.conf +++ b/zephyr/projects/npcx_evb/npcx9/prj.conf @@ -58,7 +58,4 @@ CONFIG_LOG=y # Avoid underflow info from tachometer CONFIG_SENSOR_LOG_LEVEL_ERR=y -# Avoid info storm from power management -CONFIG_SOC_LOG_LEVEL_ERR=y - CONFIG_SYSCON=y diff --git a/zephyr/projects/posix-ec/BUILD.py b/zephyr/projects/posix-ec/BUILD.py index b94d087642..a324f2ad39 100644 --- a/zephyr/projects/posix-ec/BUILD.py +++ b/zephyr/projects/posix-ec/BUILD.py @@ -2,4 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Define zmake projects for posix-ec.""" + register_host_project(project_name="posix-ec") diff --git a/zephyr/projects/skyrim/BUILD.py b/zephyr/projects/skyrim/BUILD.py index e206bdd0d5..708109590d 100644 --- a/zephyr/projects/skyrim/BUILD.py +++ b/zephyr/projects/skyrim/BUILD.py @@ -2,8 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Define zmake projects for skyrim.""" + def register_variant(project_name): + """Register a variant of skyrim.""" register_npcx_project( project_name=project_name, zephyr_board="npcx9", diff --git a/zephyr/projects/skyrim/gpio.dts b/zephyr/projects/skyrim/gpio.dts index 9c1896265d..4e717482eb 100644 --- a/zephyr/projects/skyrim/gpio.dts +++ b/zephyr/projects/skyrim/gpio.dts @@ -174,8 +174,9 @@ gpio_ec_kso_02_inv: ec_kso_02_inv { gpios = <&gpio1 7 (GPIO_OUTPUT_LOW | GPIO_ACTIVE_LOW)>; }; - tablet_mode { + tablet_mode_l { gpios = <&gpioc 1 GPIO_INPUT>; + enum-name = "GPIO_TABLET_MODE_L"; }; ec_gpio56 { gpios = <&gpio5 6 GPIO_INPUT_PULL_UP>; @@ -201,7 +202,7 @@ gpios = <&ioex_c0_port1 2 GPIO_INPUT>; enum-name = "IOEX_USB_C0_FAULT_ODL"; }; - ioex_en_pp5500_usb_a0_vbus: en_pp5500_usb_a0_vbus { + ioex_en_pp5000_usb_a0_vbus: en_pp5000_usb_a0_vbus { gpios = <&ioex_c0_port1 5 GPIO_OUTPUT_LOW>; enum-name = "IOEX_EN_PP5000_USB_A0_VBUS"; }; @@ -244,7 +245,7 @@ gpios = <&ioex_c1_port1 2 GPIO_INPUT>; enum-name = "IOEX_USB_C1_FAULT_ODL"; }; - ioex_en_pp5500_usb_a1_vbus: en_pp5500_usb_a1_vbus { + ioex_en_pp5000_usb_a1_vbus: en_pp5000_usb_a1_vbus { gpios = <&ioex_c1_port1 5 GPIO_OUTPUT_LOW>; enum-name = "IOEX_EN_PP5000_USB_A1_VBUS_DB"; }; @@ -261,8 +262,8 @@ usba-port-enable-list { compatible = "cros-ec,usba-port-enable-pins"; - enable-pins = <&ioex_en_pp5500_usb_a0_vbus - &ioex_en_pp5500_usb_a1_vbus>; + enable-pins = <&ioex_en_pp5000_usb_a0_vbus + &ioex_en_pp5000_usb_a1_vbus>; }; vsby-psl-in-list { diff --git a/zephyr/projects/skyrim/prj.conf b/zephyr/projects/skyrim/prj.conf index a9be70454b..c69ede5cfd 100644 --- a/zephyr/projects/skyrim/prj.conf +++ b/zephyr/projects/skyrim/prj.conf @@ -96,7 +96,6 @@ CONFIG_PLATFORM_EC_CHARGER_MIN_POWER_MW_FOR_POWER_ON=50000 # USB-A CONFIG_PLATFORM_EC_USBA=y -CONFIG_PLATFORM_EC_USB_PORT_POWER_DUMB=y # USB-C CONFIG_PLATFORM_EC_BC12_DETECT_PI3USB9201=y @@ -124,6 +123,8 @@ CONFIG_PLATFORM_EC_USB_PD_TCPM_NCT38XX=y CONFIG_PLATFORM_EC_USB_PD_TCPC_RUNTIME_CONFIG=n CONFIG_PLATFORM_EC_USB_PD_USB4=n CONFIG_PLATFORM_EC_USB_PD_VBUS_MEASURE_CHARGER=y +# Give ourselves enough task space to use i2ctrace +CONFIG_TASK_PD_STACK_SIZE=1280 # IOEX CONFIG_GPIO_NCT38XX=y @@ -143,6 +144,9 @@ CONFIG_PLATFORM_EC_LID_ANGLE=y CONFIG_PLATFORM_EC_LID_ANGLE_UPDATE=y CONFIG_PLATFORM_EC_SENSOR_TIGHT_TIMESTAMPS=y +CONFIG_PLATFORM_EC_TABLET_MODE=y +CONFIG_PLATFORM_EC_GMR_TABLET_MODE=y + CONFIG_PLATFORM_EC_ACCEL_BMA4XX=y CONFIG_PLATFORM_EC_ACCELGYRO_BMI3XX=y CONFIG_PLATFORM_EC_ACCELGYRO_BMI_COMM_I2C=y diff --git a/zephyr/projects/trogdor/lazor/BUILD.py b/zephyr/projects/trogdor/lazor/BUILD.py index dabaddc236..13446cb702 100644 --- a/zephyr/projects/trogdor/lazor/BUILD.py +++ b/zephyr/projects/trogdor/lazor/BUILD.py @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Define zmake projects for lazor.""" + register_npcx_project( project_name="lazor", zephyr_board="npcx7", diff --git a/zephyr/projects/trogdor/lazor/prj.conf b/zephyr/projects/trogdor/lazor/prj.conf index f95d5a4153..2a61f5854f 100644 --- a/zephyr/projects/trogdor/lazor/prj.conf +++ b/zephyr/projects/trogdor/lazor/prj.conf @@ -96,7 +96,6 @@ CONFIG_PLATFORM_EC_CONSOLE_CMD_CHARGER_ADC_AMON_BMON=y # USB-A CONFIG_PLATFORM_EC_USBA=y -CONFIG_PLATFORM_EC_USB_PORT_POWER_DUMB=y # USB-C CONFIG_PLATFORM_EC_BC12_DETECT_PI3USB9201=y @@ -116,7 +115,6 @@ CONFIG_PLATFORM_EC_USB_PD_TCPM_PS8805=y CONFIG_PLATFORM_EC_USB_PD_TCPC_RUNTIME_CONFIG=n CONFIG_PLATFORM_EC_USB_MUX_RUNTIME_CONFIG=n CONFIG_PLATFORM_EC_USB_PD_LOGGING=y -CONFIG_PLATFORM_EC_USB_PORT_POWER_DUMB=y # USB ID # This is allocated specifically for Trogdor diff --git a/zephyr/shim/include/config_chip.h b/zephyr/shim/include/config_chip.h index 2900acd9aa..5f865c3fa7 100644 --- a/zephyr/shim/include/config_chip.h +++ b/zephyr/shim/include/config_chip.h @@ -804,7 +804,8 @@ extern struct jump_data mock_jump_data; #endif #undef CONFIG_POWER_TRACK_HOST_SLEEP_STATE -#ifdef CONFIG_PLATFORM_EC_POWERSEQ_HOST_SLEEP +#if defined(CONFIG_PLATFORM_EC_POWERSEQ_HOST_SLEEP) || \ + defined(CONFIG_AP_PWRSEQ_HOST_SLEEP) #define CONFIG_POWER_TRACK_HOST_SLEEP_STATE #endif @@ -840,7 +841,8 @@ extern struct jump_data mock_jump_data; #endif #undef CONFIG_POWER_S0IX -#ifdef CONFIG_PLATFORM_EC_POWERSEQ_S0IX +#if defined(CONFIG_PLATFORM_EC_POWERSEQ_S0IX) || \ + defined(CONFIG_AP_PWRSEQ_S0IX) #define CONFIG_POWER_S0IX #endif diff --git a/zephyr/shim/include/power_host_sleep.h b/zephyr/shim/include/power_host_sleep.h new file mode 100644 index 0000000000..e4f24b7d88 --- /dev/null +++ b/zephyr/shim/include/power_host_sleep.h @@ -0,0 +1,71 @@ +/* Copyright 2022 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. + */ + +#ifndef __POWER_HOST_SLEEP_H +#define __POWER_HOST_SLEEP_H + +/* + * This file is for Zephyr ap_pwrseq to reuse legacy EC code. + * Eventually this file should be removed. + * + * TODO: Declaration in this file should be removed once it can be replaced + * by implementation in Zephyr code. + */ +#if CONFIG_AP_PWRSEQ + +#include "ec_commands.h" +#include "host_command.h" +#include "lpc.h" +#include "system.h" + +/********************************************************************/ +/* power.h */ +enum power_state { + /* Steady states */ + POWER_G3 = 0, /* + * System is off (not technically all the way into G3, + * which means totally unpowered...) + */ + POWER_S5, /* System is soft-off */ + POWER_S4, /* System is suspended to disk */ + POWER_S3, /* Suspend; RAM on, processor is asleep */ + POWER_S0, /* System is on */ +#if CONFIG_AP_PWRSEQ_S0IX + POWER_S0ix, +#endif + /* Transitions */ + POWER_G3S5, /* G3 -> S5 (at system init time) */ + POWER_S5S3, /* S5 -> S3 (skips S4 on non-Intel systems) */ + POWER_S3S0, /* S3 -> S0 */ + POWER_S0S3, /* S0 -> S3 */ + POWER_S3S5, /* S3 -> S5 (skips S4 on non-Intel systems) */ + POWER_S5G3, /* S5 -> G3 */ + POWER_S3S4, /* S3 -> S4 */ + POWER_S4S3, /* S4 -> S3 */ + POWER_S4S5, /* S4 -> S5 */ + POWER_S5S4, /* S5 -> S4 */ +#if CONFIG_AP_PWRSEQ_S0IX + POWER_S0ixS0, /* S0ix -> S0 */ + POWER_S0S0ix, /* S0 -> S0ix */ +#endif +}; + +#if CONFIG_AP_PWRSEQ_HOST_SLEEP +/* Context to pass to a host sleep command handler. */ +struct host_sleep_event_context { + uint32_t sleep_transitions; /* Number of sleep transitions observed */ + uint16_t sleep_timeout_ms; /* Timeout in milliseconds */ +}; + +void ap_power_chipset_handle_host_sleep_event( + enum host_sleep_event state, + struct host_sleep_event_context *ctx); +enum host_sleep_event power_get_host_sleep_state(void); +void power_set_host_sleep_state(enum host_sleep_event state); +#endif /* CONFIG_AP_PWRSEQ_HOST_SLEEP */ + +#endif /* CONFIG_AP_PWRSEQ */ + +#endif /* __POWER_HOST_SLEEP_H */ diff --git a/zephyr/shim/include/usbc/ppc.h b/zephyr/shim/include/usbc/ppc.h index cc989d7816..00c7c36c41 100644 --- a/zephyr/shim/include/usbc/ppc.h +++ b/zephyr/shim/include/usbc/ppc.h @@ -11,12 +11,12 @@ #include "usbc/ppc_rt1739.h" #include "usbc/ppc_sn5s330.h" #include "usbc/ppc_syv682x.h" +#include "usbc/utils.h" #include "usbc_ppc.h" #define PPC_ID(id) DT_CAT(PPC_, id) #define PPC_ID_WITH_COMMA(id) PPC_ID(id), -#define PPC_USBC_PORT(id) DT_REG_ADDR(DT_PARENT(id)) -#define PPC_ALT_FOR(alt_id) PPC_USBC_PORT(DT_PHANDLE(alt_id, alternate_for)) +#define PPC_ALT_FOR(alt_id) USBC_PORT(DT_PHANDLE(alt_id, alternate_for)) #define PPC_ALT_ENUM(id) \ COND_CODE_1(DT_NODE_HAS_PROP(id, alternate_for), \ diff --git a/zephyr/shim/include/usbc/utils.h b/zephyr/shim/include/usbc/utils.h new file mode 100644 index 0000000000..49b9aa4b71 --- /dev/null +++ b/zephyr/shim/include/usbc/utils.h @@ -0,0 +1,36 @@ +/* Copyright 2022 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. + */ + +#ifndef __CROS_EC_ZEPHYR_SHIM_USBC_UTIL + + +/* + * Enable interrupt from the `irq` property of an instance's node. + * + * @param inst: instance number + */ +#define BC12_GPIO_ENABLE_INTERRUPT(inst) \ + IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, irq), \ + (gpio_enable_dt_interrupt( \ + GPIO_INT_FROM_NODE(DT_INST_PHANDLE(inst, irq)));\ + ) \ + ) + +/* + * Get the port number from a child of `named-usbc-port` node. + * + * @param id: node id + */ +#define USBC_PORT(id) DT_REG_ADDR(DT_PARENT(id)) + +/* + * Get the port number from a child of `named-usbc-port` node. + * + * @param inst: instance number of the node + */ +#define USBC_PORT_FROM_INST(inst) USBC_PORT(DT_DRV_INST(inst)) + + +#endif /* __CROS_EC_ZEPHYR_SHIM_USBC_UTIL */ diff --git a/zephyr/shim/src/CMakeLists.txt b/zephyr/shim/src/CMakeLists.txt index 4afacd396e..bc9729abae 100644 --- a/zephyr/shim/src/CMakeLists.txt +++ b/zephyr/shim/src/CMakeLists.txt @@ -24,6 +24,8 @@ zephyr_library_sources_ifdef(no_libgcc libgcc_${ARCH}.S) zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_ADC adc.c) zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_BATTERY battery.c) +zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_CHARGER_RT9490 + bc12_rt9490.c) zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_HOST_INTERFACE_ESPI espi.c) zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_FAN fan.c) @@ -65,4 +67,4 @@ zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_USB_PD_TCPM_TCPCI tcpc.c) zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_USBA usba.c) - +zephyr_library_sources_ifdef(CONFIG_AP_PWRSEQ power_host_sleep_api.c) diff --git a/zephyr/shim/src/bc12.c b/zephyr/shim/src/bc12.c index 408458365f..fc6dfb6aa9 100644 --- a/zephyr/shim/src/bc12.c +++ b/zephyr/shim/src/bc12.c @@ -7,14 +7,13 @@ #include "usbc/bc12_pi3usb9201.h" #include "usbc/bc12_rt1739.h" #include "usbc/bc12_rt9490.h" +#include "usbc/utils.h" #include "usb_charge.h" #if DT_HAS_COMPAT_STATUS_OKAY(RT1739_BC12_COMPAT) || \ DT_HAS_COMPAT_STATUS_OKAY(RT9490_BC12_COMPAT) || \ DT_HAS_COMPAT_STATUS_OKAY(PI3USB9201_COMPAT) -#define USBC_PORT(id) DT_REG_ADDR(DT_PARENT(id)) - #define BC12_CHIP(id, fn) [USBC_PORT(id)] = fn(id) /* Power Path Controller */ diff --git a/zephyr/shim/src/bc12_pi3usb9201.c b/zephyr/shim/src/bc12_pi3usb9201.c index 49e6902e74..57e4ed7b61 100644 --- a/zephyr/shim/src/bc12_pi3usb9201.c +++ b/zephyr/shim/src/bc12_pi3usb9201.c @@ -12,6 +12,7 @@ #include "task.h" #include "usb_charge.h" #include "usb_pd.h" +#include "usbc/utils.h" #if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) @@ -30,12 +31,6 @@ const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { DT_INST_FOREACH_STATUS_OKAY(USBC_PORT_BC12) }; -#define BC12_GPIO_ENABLE_INTERRUPT(inst) \ - IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, irq), \ - (gpio_enable_dt_interrupt( \ - GPIO_INT_FROM_NODE(DT_INST_PHANDLE(inst, irq)))) \ - ); - static void bc12_enable_irqs(void) { DT_INST_FOREACH_STATUS_OKAY(BC12_GPIO_ENABLE_INTERRUPT) diff --git a/zephyr/shim/src/bc12_rt9490.c b/zephyr/shim/src/bc12_rt9490.c new file mode 100644 index 0000000000..68798241d5 --- /dev/null +++ b/zephyr/shim/src/bc12_rt9490.c @@ -0,0 +1,41 @@ +/* Copyright 2022 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define DT_DRV_COMPAT richtek_rt9490_bc12 + +#include <devicetree.h> +#include "driver/charger/rt9490.h" +#include "gpio/gpio_int.h" +#include "hooks.h" +#include "usbc/utils.h" + +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) + +static void rt9490_bc12_enable_irqs(void) +{ + DT_INST_FOREACH_STATUS_OKAY(BC12_GPIO_ENABLE_INTERRUPT); +} +DECLARE_HOOK(HOOK_INIT, rt9490_bc12_enable_irqs, HOOK_PRIO_DEFAULT); + +#define GPIO_SIGNAL_FROM_INST(inst) \ + GPIO_SIGNAL(DT_PHANDLE(DT_INST_PHANDLE(inst, irq), irq_pin)) + +#define RT9490_DISPATCH_INTERRUPT(inst) \ + IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, irq), \ + (case GPIO_SIGNAL_FROM_INST(inst): \ + rt9490_interrupt(USBC_PORT_FROM_INST(inst)); \ + break; \ + )) + +void rt9490_bc12_dt_interrupt(enum gpio_signal signal) +{ + switch (signal) { + DT_INST_FOREACH_STATUS_OKAY(RT9490_DISPATCH_INTERRUPT); + default: + break; + } +} + +#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */ diff --git a/zephyr/shim/src/espi.c b/zephyr/shim/src/espi.c index 37a051e57c..31cc51f9fc 100644 --- a/zephyr/shim/src/espi.c +++ b/zephyr/shim/src/espi.c @@ -83,6 +83,7 @@ static bool init_done; return B; #define CASE_ZEPHYR_TO_CROS(A, B) CASE_CROS_TO_ZEPHYR(B, A) +#if !defined(CONFIG_AP_PWRSEQ) /* Translate a platform/ec signal to a Zephyr signal */ static enum espi_vwire_signal signal_to_zephyr_vwire(enum espi_vw_signal signal) { @@ -138,6 +139,8 @@ static void espi_vwire_handler(const struct device *dev, } } +#endif /* !defined(CONFIG_AP_PWRSEQ) */ + #ifdef CONFIG_PLATFORM_EC_CHIPSET_RESET_HOOK static void espi_chipset_reset(void) { @@ -161,6 +164,7 @@ static void espi_reset_handler(const struct device *dev, #define espi_dev DEVICE_DT_GET(DT_CHOSEN(cros_ec_espi)) +#if !defined(CONFIG_AP_PWRSEQ) int espi_vw_set_wire(enum espi_vw_signal signal, uint8_t level) { @@ -198,6 +202,8 @@ int espi_vw_disable_wire_int(enum espi_vw_signal signal) return 0; } +#endif /* !defined(CONFIG_AP_PWRSEQ) */ + uint8_t *lpc_get_memmap_range(void) { uint32_t lpc_memmap = 0; @@ -228,6 +234,8 @@ static void lpc_update_wake(host_event_t wake_events) !wake_events); } +#if !defined(CONFIG_AP_PWRSEQ) + static void lpc_generate_smi(void) { /* Enforce signal-high for long enough to debounce high */ @@ -248,6 +256,33 @@ static void lpc_generate_sci(void) espi_vw_set_wire(VW_SCI_L, 1); } +#else + +/* + * Use Zephyr API. + */ +static void lpc_generate_signal(enum espi_vwire_signal signal) +{ + /* Enforce signal-high for long enough to debounce high */ + espi_send_vwire(espi_dev, signal, 1); + udelay(VWIRE_PULSE_TRIGGER_TIME); + espi_send_vwire(espi_dev, signal, 0); + udelay(VWIRE_PULSE_TRIGGER_TIME); + espi_send_vwire(espi_dev, signal, 1); +} + +static void lpc_generate_sci(void) +{ + lpc_generate_signal(ESPI_VWIRE_SIGNAL_SCI); +} + +static void lpc_generate_smi(void) +{ + lpc_generate_signal(ESPI_VWIRE_SIGNAL_SMI); +} + +#endif /* !defined(CONFIG_AP_PWRSEQ) */ + void lpc_update_host_event_status(void) { uint32_t enable; @@ -523,10 +558,12 @@ static int zephyr_shim_setup_espi(const struct device *unused) espi_callback_handler_t handler; enum espi_bus_event event_type; } callbacks[] = { +#if !defined(CONFIG_AP_PWRSEQ) { .handler = espi_vwire_handler, .event_type = ESPI_BUS_EVENT_VWIRE_RECEIVED, }, +#endif { .handler = espi_peripheral_handler, .event_type = ESPI_BUS_PERIPHERAL_NOTIFICATION, diff --git a/zephyr/shim/src/led_driver/led.h b/zephyr/shim/src/led_driver/led.h index 53728609ed..086d2312b5 100644 --- a/zephyr/shim/src/led_driver/led.h +++ b/zephyr/shim/src/led_driver/led.h @@ -6,6 +6,8 @@ #ifndef __CROS_EC_LED_H__ #define __CROS_EC_LED_H__ +#include <devicetree.h> + #define COMPAT_GPIO_LED cros_ec_gpio_led_pins #define COMPAT_PWM_LED cros_ec_pwm_led_pins @@ -19,11 +21,22 @@ (DT_STRING_UPPER_TOKEN(id, prop)), \ (-1)) -/* TODO(b/227798487): Use DT to generate this enum instead of hardcoding */ +#define LED_ENUM(id, enum_name) DT_STRING_TOKEN(id, enum_name) +#define LED_ENUM_WITH_COMMA(id, enum_name) \ + COND_CODE_1(DT_NODE_HAS_PROP(id, enum_name), \ + (LED_ENUM(id, enum_name),), ()) + +#define GPIO_LED_PINS_NODE DT_PATH(gpio_led_pins) +#define PWM_LED_PINS_NODE DT_PATH(pwm_led_pins) + enum led_color { - LED_OFF = 0, - LED_AMBER, - LED_BLUE, +#if DT_NODE_EXISTS(GPIO_LED_PINS_NODE) + DT_FOREACH_CHILD_VARGS(GPIO_LED_PINS_NODE, + LED_ENUM_WITH_COMMA, led_color) +#elif DT_NODE_EXISTS(PWM_LED_PINS_NODE) + DT_FOREACH_CHILD_VARGS(PWM_LED_PINS_NODE, + LED_ENUM_WITH_COMMA, led_color) +#endif LED_COLOR_COUNT /* Number of colors, not a color itself */ }; diff --git a/zephyr/shim/src/led_driver/led_gpio.c b/zephyr/shim/src/led_driver/led_gpio.c index 85bdc2dd71..9107aad579 100644 --- a/zephyr/shim/src/led_driver/led_gpio.c +++ b/zephyr/shim/src/led_driver/led_gpio.c @@ -17,7 +17,6 @@ LOG_MODULE_REGISTER(gpio_led, LOG_LEVEL_ERR); -#define GPIO_LED_PINS_NODE DT_PATH(gpio_led_pins) #define LED_PIN_COUNT (LED_COLOR_COUNT - 1) /* diff --git a/zephyr/shim/src/led_driver/led_pwm.c b/zephyr/shim/src/led_driver/led_pwm.c index d2605256a5..d2466e0d60 100644 --- a/zephyr/shim/src/led_driver/led_pwm.c +++ b/zephyr/shim/src/led_driver/led_pwm.c @@ -17,7 +17,6 @@ LOG_MODULE_REGISTER(pwm_led, LOG_LEVEL_ERR); -#define PWM_LED_PINS_NODE DT_PATH(pwm_led_pins) #define LED_PIN_COUNT (LED_COLOR_COUNT - 1) /* diff --git a/zephyr/shim/src/power_host_sleep_api.c b/zephyr/shim/src/power_host_sleep_api.c new file mode 100644 index 0000000000..d22f4fe4c4 --- /dev/null +++ b/zephyr/shim/src/power_host_sleep_api.c @@ -0,0 +1,45 @@ +/* Copyright 2022 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 <kernel.h> + +#include <ap_power/ap_power_interface.h> +#include <power_host_sleep.h> + +static enum power_state translate_ap_power_state( + enum power_states_ndsx ap_power_state) +{ + switch (ap_power_state) { + case SYS_POWER_STATE_S5: + return POWER_S5; + case SYS_POWER_STATE_S3: + return POWER_S3; +#if CONFIG_AP_PWRSEQ_S0IX + case SYS_POWER_STATE_S0ix: + return POWER_S0ix; +#endif + default: + return 0; + } +} + +int ap_power_get_lazy_wake_mask( + enum power_states_ndsx state, host_event_t *mask) +{ + enum power_state st; + + st = translate_ap_power_state(state); + if (!st) + return -EINVAL; + return get_lazy_wake_mask(st, mask); +} + +#if CONFIG_AP_PWRSEQ_HOST_SLEEP +void power_chipset_handle_host_sleep_event( + enum host_sleep_event state, + struct host_sleep_event_context *ctx) +{ + ap_power_chipset_handle_host_sleep_event(state, ctx); +} +#endif diff --git a/zephyr/shim/src/ppc.c b/zephyr/shim/src/ppc.c index b8c50f7a24..a77f7aa656 100644 --- a/zephyr/shim/src/ppc.c +++ b/zephyr/shim/src/ppc.c @@ -22,7 +22,7 @@ COND_CODE_1(DT_NODE_HAS_PROP(id, alternate_for), \ (PPC_CHIP_ELE_ALT(id, fn)), ()) -#define PPC_CHIP_ELE_PRIM(id, fn) [PPC_USBC_PORT(id)] = fn(id) +#define PPC_CHIP_ELE_PRIM(id, fn) [USBC_PORT(id)] = fn(id) #define PPC_CHIP_ELE_ALT(id, fn) [PPC_ID(id)] = fn(id) diff --git a/zephyr/shim/src/tasks.c b/zephyr/shim/src/tasks.c index 5b8fb502be..7c0d758d66 100644 --- a/zephyr/shim/src/tasks.c +++ b/zephyr/shim/src/tasks.c @@ -48,20 +48,20 @@ struct task_ctx_cfg { intptr_t parameter; }; +struct task_ctx_base_data { + /** A wait-able event that is raised when a new task event is posted */ + struct k_poll_signal new_event; + /** The current platform/ec events set for this task/thread */ + atomic_t event_mask; +}; + struct task_ctx_data { /** Zephyr thread structure that hosts EC tasks */ struct k_thread zephyr_thread; /** Zephyr thread id for above thread */ k_tid_t zephyr_tid; - /** A wait-able event that is raised when a new task event is posted */ - struct k_poll_signal new_event; - /** The current platform/ec events set for this task/thread */ - atomic_t event_mask; - /** - * The timer associated with this task, which can be set using - * timer_arm(). - */ - struct k_timer timer; + /** Base context data */ + struct task_ctx_base_data base; }; #define CROS_EC_TASK(_name, _entry, _parameter, _size) \ @@ -74,7 +74,6 @@ struct task_ctx_data { }, #define TASK_TEST(_name, _entry, _parameter, _size) \ CROS_EC_TASK(_name, _entry, _parameter, _size) -/* Note: no static entry is required for sysworkq, as it isn't started here */ const static struct task_ctx_cfg shimmed_tasks_cfg[TASK_ID_COUNT] = { CROS_EC_TASK_LIST #ifdef TEST_BUILD @@ -82,8 +81,13 @@ const static struct task_ctx_cfg shimmed_tasks_cfg[TASK_ID_COUNT] = { #endif }; -/* In tasks data, allocate one extra spot for the sysworkq */ -static struct task_ctx_data shimmed_tasks_data[TASK_ID_COUNT + 1]; +static struct task_ctx_data shimmed_tasks_data[TASK_ID_COUNT]; +static struct task_ctx_base_data sysworkq_task_data; +/* Task timer structures, one extra for TASK_ID_SYSWORKQ. Keep separate from + * the context ones to avoid memory holes due to int64_t fields in struct + * _timeout. + */ +static struct k_timer shimmed_tasks_timers[TASK_ID_COUNT + 1]; #define TASK_ID_SYSWORKQ TASK_ID_COUNT @@ -91,10 +95,22 @@ static int tasks_started; #undef CROS_EC_TASK #undef TASK_TEST +static struct task_ctx_base_data *task_get_base_data(task_id_t cros_task_id) +{ + if (cros_task_id == TASK_ID_SYSWORKQ) { + return &sysworkq_task_data; + } + + return &shimmed_tasks_data[cros_task_id].base; +} + task_id_t task_get_current(void) { - /* Include sysworkq entry in search for the task ID */ - for (size_t i = 0; i < TASK_ID_COUNT + 1; ++i) { + if (in_deferred_context()) { + return TASK_ID_SYSWORKQ; + } + + for (size_t i = 0; i < TASK_ID_COUNT; ++i) { if (shimmed_tasks_data[i].zephyr_tid == k_current_get()) return i; } @@ -103,21 +119,20 @@ task_id_t task_get_current(void) return 0; } -__test_only k_tid_t task_get_zephyr_tid(size_t cros_tid) -{ - return shimmed_tasks_data[cros_tid].zephyr_tid; -} - atomic_t *task_get_event_bitmap(task_id_t cros_task_id) { - struct task_ctx_data *const data = &shimmed_tasks_data[cros_task_id]; + struct task_ctx_base_data *data; + + data = task_get_base_data(cros_task_id); return &data->event_mask; } uint32_t task_set_event(task_id_t cros_task_id, uint32_t event) { - struct task_ctx_data *const data = &shimmed_tasks_data[cros_task_id]; + struct task_ctx_base_data *data; + + data = task_get_base_data(cros_task_id); atomic_or(&data->event_mask, event); k_poll_signal_raise(&data->new_event, 0); @@ -127,8 +142,10 @@ uint32_t task_set_event(task_id_t cros_task_id, uint32_t event) uint32_t task_wait_event(int timeout_us) { - struct task_ctx_data *const data = - &shimmed_tasks_data[task_get_current()]; + struct task_ctx_base_data *data; + + data = task_get_base_data(task_get_current()); + const k_timeout_t timeout = (timeout_us == -1) ? K_FOREVER : K_USEC(timeout_us); const int64_t tick_deadline = @@ -170,8 +187,10 @@ uint32_t task_wait_event(int timeout_us) uint32_t task_wait_event_mask(uint32_t event_mask, int timeout_us) { - struct task_ctx_data *const data = - &shimmed_tasks_data[task_get_current()]; + struct task_ctx_base_data *data; + + data = task_get_base_data(task_get_current()); + uint32_t events = 0; const int64_t tick_deadline = k_uptime_ticks() + k_us_to_ticks_near64(timeout_us); @@ -228,17 +247,17 @@ static void task_entry(void *task_context_cfg, */ static void timer_expire(struct k_timer *timer_id) { - struct task_ctx_data *const data = - CONTAINER_OF(timer_id, struct task_ctx_data, timer); - task_id_t cros_ec_task_id = data - shimmed_tasks_data; + task_id_t cros_ec_task_id = timer_id - shimmed_tasks_timers; task_set_event(cros_ec_task_id, TASK_EVENT_TIMER); } int timer_arm(timestamp_t event, task_id_t cros_ec_task_id) { + struct k_timer *timer; timestamp_t now = get_time(); - struct task_ctx_data *const data = &shimmed_tasks_data[cros_ec_task_id]; + + timer = &shimmed_tasks_timers[cros_ec_task_id]; if (event.val <= now.val) { /* Timer requested for now or in the past, fire right away */ @@ -247,18 +266,20 @@ int timer_arm(timestamp_t event, task_id_t cros_ec_task_id) } /* Check for a running timer */ - if (k_timer_remaining_get(&data->timer)) + if (k_timer_remaining_get(timer)) return EC_ERROR_BUSY; - k_timer_start(&data->timer, K_USEC(event.val - now.val), K_NO_WAIT); + k_timer_start(timer, K_USEC(event.val - now.val), K_NO_WAIT); return EC_SUCCESS; } void timer_cancel(task_id_t cros_ec_task_id) { - struct task_ctx_data *const data = &shimmed_tasks_data[cros_ec_task_id]; + struct k_timer *timer; + + timer = &shimmed_tasks_timers[cros_ec_task_id]; - k_timer_stop(&data->timer); + k_timer_stop(timer); } #ifdef TEST_BUILD @@ -288,13 +309,14 @@ void start_ec_tasks(void) { int priority; - /* Initialize all EC tasks, which does not include the sysworkq entry */ + for (size_t i = 0; i < TASK_ID_COUNT + 1; ++i) { + k_timer_init(&shimmed_tasks_timers[i], timer_expire, NULL); + } + for (size_t i = 0; i < TASK_ID_COUNT; ++i) { struct task_ctx_data *const data = &shimmed_tasks_data[i]; const struct task_ctx_cfg *const cfg = &shimmed_tasks_cfg[i]; - k_timer_init(&data->timer, timer_expire, NULL); - priority = K_PRIO_PREEMPT(TASK_ID_COUNT - i - 1); #ifdef TEST_BUILD @@ -342,9 +364,6 @@ void start_ec_tasks(void) #endif } - /* Create an entry for sysworkq we can send events to */ - shimmed_tasks_data[TASK_ID_COUNT].zephyr_tid = &k_sys_work_q.thread; - tasks_started = 1; } @@ -357,13 +376,14 @@ int init_signals(const struct device *unused) { ARG_UNUSED(unused); - /* Initialize event structures for all entries, including sysworkq */ - for (size_t i = 0; i < TASK_ID_COUNT + 1; ++i) { + for (size_t i = 0; i < TASK_ID_COUNT; ++i) { struct task_ctx_data *const data = &shimmed_tasks_data[i]; - k_poll_signal_init(&data->new_event); + k_poll_signal_init(&data->base.new_event); } + k_poll_signal_init(&sysworkq_task_data.new_event); + return 0; } SYS_INIT(init_signals, POST_KERNEL, 50); diff --git a/zephyr/shim/src/tcpc.c b/zephyr/shim/src/tcpc.c index 98f631757c..82f53d70d9 100644 --- a/zephyr/shim/src/tcpc.c +++ b/zephyr/shim/src/tcpc.c @@ -11,14 +11,13 @@ #include "usbc/tcpc_it8xxx2.h" #include "usbc/tcpc_ps8xxx.h" #include "usbc/tcpci.h" +#include "usbc/utils.h" #if DT_HAS_COMPAT_STATUS_OKAY(FUSB302_TCPC_COMPAT) || \ DT_HAS_COMPAT_STATUS_OKAY(IT8XXX2_TCPC_COMPAT) || \ DT_HAS_COMPAT_STATUS_OKAY(PS8XXX_COMPAT) || \ DT_HAS_COMPAT_STATUS_OKAY(TCPCI_COMPAT) \ -#define USBC_PORT(id) DT_REG_ADDR(DT_PARENT(id)) - #define TCPC_CONFIG(id, fn) [USBC_PORT(id)] = fn(id) #define MAYBE_CONST COND_CODE_1(CONFIG_PLATFORM_EC_USB_PD_TCPC_RUNTIME_CONFIG, \ diff --git a/zephyr/subsys/ap_pwrseq/CMakeLists.txt b/zephyr/subsys/ap_pwrseq/CMakeLists.txt index 2eba5ae67a..2cea0a992a 100644 --- a/zephyr/subsys/ap_pwrseq/CMakeLists.txt +++ b/zephyr/subsys/ap_pwrseq/CMakeLists.txt @@ -6,6 +6,7 @@ zephyr_library_sources( ) zephyr_library_sources_ifdef(CONFIG_AP_PWRSEQ ap_power_interface.c + power_host_sleep.c power_signals.c signal_gpio.c signal_vw.c diff --git a/zephyr/subsys/ap_pwrseq/Kconfig b/zephyr/subsys/ap_pwrseq/Kconfig index 1de6d7251d..99ad4c819d 100644 --- a/zephyr/subsys/ap_pwrseq/Kconfig +++ b/zephyr/subsys/ap_pwrseq/Kconfig @@ -64,10 +64,19 @@ config X86_NON_DSX_PWRSEQ_CONSOLE This option enables Non Deep Sleep Well power sequencing shell console commands to debug. +config AP_PWRSEQ_HOST_SLEEP + bool "Handle host sleep state changes" + help + Enable AP power sequencing to receive and process host command + host sleep state changes. + config AP_PWRSEQ_S0IX - bool "Enable S0ix power state" + bool "Enable power state S0ix for Intel x86 chipset" + select AP_PWRSEQ_HOST_SLEEP default n help - This option enables power state S0ix for Intel x86 chipset. + This option enables power state S0ix for Intel x86 chipset. As + required, AP_PWRSEQ_HOST_SLEEP for host sleep event handling is + enabled. endif diff --git a/zephyr/subsys/ap_pwrseq/include/ap_power_host_sleep.h b/zephyr/subsys/ap_pwrseq/include/ap_power_host_sleep.h new file mode 100644 index 0000000000..d3cbc8c15f --- /dev/null +++ b/zephyr/subsys/ap_pwrseq/include/ap_power_host_sleep.h @@ -0,0 +1,52 @@ +/* Copyright 2022 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. + */ + +#ifndef __AP_POWER_HOST_SLEEP_H +#define __AP_POWER_HOST_SLEEP_H + +#include <ap_power/ap_power_interface.h> +#include <power_host_sleep.h> + +/* + * Deferred call to set active mask according to current power state + */ +void ap_power_set_active_wake_mask(void); + +/* + * Get lazy wake masks for the sleep state provided + * + * @param state Power state + * @param mask Lazy wake mask. + * + * @return 0 for success; -EINVAL if power state is not S3/S5/S0ix + */ +int ap_power_get_lazy_wake_mask( + enum power_states_ndsx state, host_event_t *mask); + +#if CONFIG_AP_PWRSEQ_S0IX +/* For S0ix path, flag to notify sleep change */ +enum ap_power_sleep_type { + AP_POWER_SLEEP_NONE, + AP_POWER_SLEEP_SUSPEND, + AP_POWER_SLEEP_RESUME, +}; + +/* + * Reset host sleep state and clean up + */ +void ap_power_reset_host_sleep_state(void); + +/* + * Check if the sleep type current power transition indicates is the same + * as what is notified. If same, means host sleep event notified by AP + * through Host Command and SLP_S0 are consistent. Process + * the transition. Otherwise, no action. + * + * @param check_state Sleep type which is going to transit to. + */ +void ap_power_sleep_notify_transition(enum ap_power_sleep_type check_state); +#endif /* CONFIG_AP_PWRSEQ_S0IX */ + +#endif /* __AP_PWRSEQ_HOST_SLEEP_H */ diff --git a/zephyr/subsys/ap_pwrseq/include/power_signals.h b/zephyr/subsys/ap_pwrseq/include/power_signals.h index cdeb9ec783..bc2d79bd1e 100644 --- a/zephyr/subsys/ap_pwrseq/include/power_signals.h +++ b/zephyr/subsys/ap_pwrseq/include/power_signals.h @@ -160,28 +160,36 @@ int power_signal_get(enum power_signal signal); int power_signal_set(enum power_signal signal, int value); /** - * @brief Enable interrupts for this power signal + * @brief Enable this power signal * - * For signals that allow an interrupt to be used, - * enable the interrupt. + * Enable this signal to be used as a power_signal. + * Typically this means the interrupt associated with this + * signal is enabled. * - * @param signal The power_signal to enable interrupts for. + * Power signals are enabled by default at startup, and if + * a power signal is disabled via power_signal_disable(), it will + * need to be re-enabled before the signal is included in the + * input handling again. + * + * @param signal The power_signal to enable. * @return 0 is successful - * @return negative If interrupt cannot be enabled. + * @return negative If unsuccessful */ -int power_signal_enable_interrupt(enum power_signal signal); +int power_signal_enable(enum power_signal signal); /** - * @brief Disable interrupts for this power signal + * @brief Disable this power signal * - * For signals that allow an interrupt to be used, - * disable the interrupt. + * Disable the signal so that it does not update the + * input handling (i.e does not call power_signal_interrupt() etc.) + * Once disabled, a signal must be re-enabled using + * power_signal_enable() to allow the signal to be used again. * - * @param signal The power_signal to disable interrupts for. + * @param signal The power_signal to disable. * @return 0 is successful - * @return negative If interrupt are not available on this signal. + * @return negative If unsuccessful */ -int power_signal_disable_interrupt(enum power_signal signal); +int power_signal_disable(enum power_signal signal); /** * @brief Get the debug name associated with this signal. @@ -202,7 +210,8 @@ void power_signal_init(void); /** * @brief Power signal interrupt handler * - * Called when an input signal causes an interrupt. + * Called when an input signal has changed. + * May be called from interrupt context. * * @param signal The power_signal that has changed. * @param value The new value of the signal diff --git a/zephyr/subsys/ap_pwrseq/include/signal_adc.h b/zephyr/subsys/ap_pwrseq/include/signal_adc.h index 92570beef1..e43e73e1a7 100644 --- a/zephyr/subsys/ap_pwrseq/include/signal_adc.h +++ b/zephyr/subsys/ap_pwrseq/include/signal_adc.h @@ -41,6 +41,30 @@ DT_FOREACH_STATUS_OKAY(intel_ap_pwrseq_adc, PWR_ADC_ENUM) int power_signal_adc_get(enum pwr_sig_adc adc); /** + * @brief Enable the ADC signal. + * + * This will not only enable the interrupt driven update + * of this signal, but will also enable the ADC itself. + * + * @param signal The pwr_sig_adc to enable. + * @return 0 if successful + * @return -error if failed + */ +int power_signal_adc_enable(enum pwr_sig_adc adc); + +/** + * @brief Disable the ADC signal. + * + * This will disable the interrupt updating of this signal, and will + * also disable the ADC from running. + * + * @param signal The pwr_sig_adc to disable. + * @return 0 if successful + * @return -error if failed + */ +int power_signal_adc_disable(enum pwr_sig_adc adc); + +/** * @brief Initialize the ADCs for the power signals. */ void power_signal_adc_init(void); diff --git a/zephyr/subsys/ap_pwrseq/include/signal_gpio.h b/zephyr/subsys/ap_pwrseq/include/signal_gpio.h index 04d45b8b1d..e797f0c21f 100644 --- a/zephyr/subsys/ap_pwrseq/include/signal_gpio.h +++ b/zephyr/subsys/ap_pwrseq/include/signal_gpio.h @@ -54,7 +54,7 @@ int power_signal_gpio_set(enum pwr_sig_gpio gpio, int value); * @return 0 if successful * @return -error if failed */ -int power_signal_gpio_enable_int(enum pwr_sig_gpio gpio); +int power_signal_gpio_enable(enum pwr_sig_gpio gpio); /** * @brief Disable the GPIO interrupt @@ -63,7 +63,7 @@ int power_signal_gpio_enable_int(enum pwr_sig_gpio gpio); * @return 0 if successful * @return -error if failed */ -int power_signal_gpio_disable_int(enum pwr_sig_gpio gpio); +int power_signal_gpio_disable(enum pwr_sig_gpio gpio); /** * @brief Initialize the GPIOs for the power signals. diff --git a/zephyr/subsys/ap_pwrseq/include/x86_non_dsx_common_pwrseq_sm_handler.h b/zephyr/subsys/ap_pwrseq/include/x86_non_dsx_common_pwrseq_sm_handler.h index b2ce4f74e1..cd7aa87b1d 100644 --- a/zephyr/subsys/ap_pwrseq/include/x86_non_dsx_common_pwrseq_sm_handler.h +++ b/zephyr/subsys/ap_pwrseq/include/x86_non_dsx_common_pwrseq_sm_handler.h @@ -9,9 +9,10 @@ #include <init.h> #include <kernel.h> #include <zephyr/types.h> + #include <ap_power/ap_power.h> #include <ap_power/ap_power_events.h> - +#include <ap_power_host_sleep.h> #include <x86_common_pwrseq.h> #define DT_DRV_COMPAT intel_ap_pwrseq @@ -24,7 +25,7 @@ void init_chipset_pwr_seq_state(void); void request_exit_hardoff(bool should_exit); enum power_states_ndsx pwr_sm_get_state(void); void apshutdown(void); - +void ap_pwrseq_handle_chipset_reset(void); extern const char pwrsm_dbg[][25]; #endif /* __X86_NON_DSX_COMMON_PWRSEQ_SM_HANDLER_H__ */ diff --git a/zephyr/subsys/ap_pwrseq/power_host_sleep.c b/zephyr/subsys/ap_pwrseq/power_host_sleep.c new file mode 100644 index 0000000000..13e6aba765 --- /dev/null +++ b/zephyr/subsys/ap_pwrseq/power_host_sleep.c @@ -0,0 +1,231 @@ +/* Copyright 2022 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 <ap_power/ap_power_interface.h> +#include <x86_non_dsx_common_pwrseq_sm_handler.h> + +LOG_MODULE_DECLARE(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL); + +#if CONFIG_PLATFORM_EC_HOST_INTERFACE_ESPI + +/* If host doesn't program S0ix lazy wake mask, use default S0ix mask */ +#define DEFAULT_WAKE_MASK_S0IX (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) | \ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_MODE_CHANGE)) + +/* + * Set the wake mask according to the current power state: + * 1. On transition to S0, wake mask is reset. + * 2. In non-S0 states, active mask set by host gets a higher preference. + * 3. If host has not set any active mask, then check if a lazy mask exists + * for the current power state. + * 4. If state is S0ix and no lazy or active wake mask is set, then use default + * S0ix mask to be compatible with older BIOS versions. + */ +void power_update_wake_mask(void) +{ + host_event_t wake_mask; + enum power_states_ndsx state; + + state = pwr_sm_get_state(); + + if (state == SYS_POWER_STATE_S0) + wake_mask = 0; + else if (lpc_is_active_wm_set_by_host() || + ap_power_get_lazy_wake_mask(state, &wake_mask)) + return; +#if CONFIG_AP_PWRSEQ_S0IX + if ((state == SYS_POWER_STATE_S0ix) && (wake_mask == 0)) + wake_mask = DEFAULT_WAKE_MASK_S0IX; +#endif + + lpc_set_host_event_mask(LPC_HOST_EVENT_WAKE, wake_mask); +} + +static void power_update_wake_mask_deferred(struct k_work *work) +{ + power_update_wake_mask(); +} + +static K_WORK_DELAYABLE_DEFINE( + power_update_wake_mask_deferred_data, power_update_wake_mask_deferred); + +void ap_power_set_active_wake_mask(void) +{ + int rv; + + /* + * Allow state machine to stabilize and update wake mask after 5msec. It + * was observed that on platforms where host wakes up periodically from + * S0ix for hardware book-keeping activities, there is a small window + * where host is not really up and running software, but still SLP_S0# + * is de-asserted and hence setting wake mask right away can cause user + * wake events to be missed. + * + * Time for deferred callback was chosen to be 5msec based on the fact + * that it takes ~2msec for the periodic wake cycle to complete on the + * host for KBL. + */ + rv = k_work_schedule(&power_update_wake_mask_deferred_data, K_MSEC(5)); + if (rv == 0) { + /* + * A work is already scheduled or submitted, since power state + * has changed again and the work is not processed, we should + * reschedule it. + */ + rv = k_work_reschedule( + &power_update_wake_mask_deferred_data, K_MSEC(5)); + } + __ASSERT(rv >= 0, "Set wake mask work queue error"); +} + +#else /* CONFIG_PLATFORM_EC_HOST_INTERFACE_ESPI */ +static void ap_power_set_active_wake_mask(void) { } +#endif /* CONFIG_PLATFORM_EC_HOST_INTERFACE_ESPI */ + +#if CONFIG_AP_PWRSEQ_S0IX +/* + * Backup copies of SCI and SMI mask to preserve across S0ix suspend/resume + * cycle. If the host uses S0ix, BIOS is not involved during suspend and resume + * operations and hence SCI/SMI masks are programmed only once during boot-up. + * + * These backup variables are set whenever host expresses its interest to + * enter S0ix and then lpc_host_event_mask for SCI and SMI are cleared. When + * host resumes from S0ix, masks from backup variables are copied over to + * lpc_host_event_mask for SCI and SMI. + */ +static host_event_t backup_sci_mask; +static host_event_t backup_smi_mask; + +/* Flag to notify listeners about suspend/resume events. */ +enum ap_power_sleep_type sleep_state = AP_POWER_SLEEP_NONE; + +/* + * Clear host event masks for SMI and SCI when host is entering S0ix. This is + * done to prevent any SCI/SMI interrupts when the host is in suspend. Since + * BIOS is not involved in the suspend path, EC needs to take care of clearing + * these masks. + */ +static void power_s0ix_suspend_clear_masks(void) +{ + backup_sci_mask = lpc_get_host_event_mask(LPC_HOST_EVENT_SCI); + backup_smi_mask = lpc_get_host_event_mask(LPC_HOST_EVENT_SMI); + lpc_set_host_event_mask(LPC_HOST_EVENT_SCI, 0); + lpc_set_host_event_mask(LPC_HOST_EVENT_SMI, 0); +} + +/* + * Restore host event masks for SMI and SCI when host exits S0ix. This is done + * because BIOS is not involved in the resume path and so EC needs to restore + * the masks from backup variables. + */ +static void power_s0ix_resume_restore_masks(void) +{ + /* + * No need to restore SCI/SMI masks if both backup_sci_mask and + * backup_smi_mask are zero. This indicates that there was a failure to + * enter S0ix(SLP_S0# assertion) and hence SCI/SMI masks were never + * backed up. + */ + if (!backup_sci_mask && !backup_smi_mask) + return; + lpc_set_host_event_mask(LPC_HOST_EVENT_SCI, backup_sci_mask); + lpc_set_host_event_mask(LPC_HOST_EVENT_SMI, backup_smi_mask); + backup_sci_mask = backup_smi_mask = 0; +} + +/* + * Following functions are called in the S0ix path, not S3 path. + */ + +/* + * Notify the sleep type that is going to transit to; this is a token to + * ensure both host sleep event passed by Host Command and SLP_S0 satisfy + * the conditions to suspend or resume. + * + * @param new_state Notified sleep type + */ +static void ap_power_sleep_set_notify(enum ap_power_sleep_type new_state) +{ + sleep_state = new_state; +} + +void ap_power_sleep_notify_transition(enum ap_power_sleep_type check_state) +{ + if (sleep_state != check_state) + return; + + if (check_state == AP_POWER_SLEEP_SUSPEND) { + /* + * Transition to S0ix; + * clear mask before others running suspend. + */ + power_s0ix_suspend_clear_masks(); + ap_power_ev_send_callbacks(AP_POWER_SUSPEND); + } else if (check_state == AP_POWER_SLEEP_RESUME) { + ap_power_ev_send_callbacks(AP_POWER_RESUME); + } + + /* Transition is done; reset sleep state. */ + ap_power_sleep_set_notify(AP_POWER_SLEEP_NONE); +} +#endif /* CONFIG_AP_PWRSEQ_S0IX */ + +#if CONFIG_AP_PWRSEQ_HOST_SLEEP +#define HOST_SLEEP_EVENT_DEFAULT_RESET 0 + +void ap_power_reset_host_sleep_state(void) +{ + power_set_host_sleep_state(HOST_SLEEP_EVENT_DEFAULT_RESET); + ap_power_chipset_handle_host_sleep_event( + HOST_SLEEP_EVENT_DEFAULT_RESET, NULL); +} + +/* TODO: hook to reset event */ +void ap_power_handle_chipset_reset(void) +{ + if (ap_power_in_state(AP_POWER_STATE_STANDBY)) + ap_power_reset_host_sleep_state(); +} + +void ap_power_chipset_handle_host_sleep_event( + enum host_sleep_event state, + struct host_sleep_event_context *ctx) +{ + LOG_DBG("host sleep event = %d!", state); +#if CONFIG_AP_PWRSEQ_S0IX + if (state == HOST_SLEEP_EVENT_S0IX_SUSPEND) { + + /* + * Indicate to power state machine that a new host event for + * s0ix/s3 suspend has been received and so chipset suspend + * notification needs to be sent to listeners. + */ + ap_power_sleep_set_notify(AP_POWER_SLEEP_SUSPEND); + power_signal_enable_interrupt(PWR_SLP_S0); + + } else if (state == HOST_SLEEP_EVENT_S0IX_RESUME) { + /* + * Set sleep state to resume; restore SCI/SMI masks; + * SLP_S0 should be de-asserted already, disable interrupt. + */ + ap_power_sleep_set_notify(AP_POWER_SLEEP_RESUME); + power_s0ix_resume_restore_masks(); + power_signal_disable_interrupt(PWR_SLP_S0); + + /* + * If the sleep signal timed out and never transitioned, then + * the wake mask was modified to its suspend state (S0ix), so + * that the event wakes the system. Explicitly restore the wake + * mask to its S0 state now. + */ + power_update_wake_mask(); + + } else if (state == HOST_SLEEP_EVENT_DEFAULT_RESET) { + power_signal_disable_interrupt(PWR_SLP_S0); + } +#endif /* CONFIG_AP_PWRSEQ_S0IX */ +} + +#endif /* CONFIG_AP_PWRSEQ_HOST_SLEEP */ diff --git a/zephyr/subsys/ap_pwrseq/power_signals.c b/zephyr/subsys/ap_pwrseq/power_signals.c index e6bdb05954..c463e8e82e 100644 --- a/zephyr/subsys/ap_pwrseq/power_signals.c +++ b/zephyr/subsys/ap_pwrseq/power_signals.c @@ -226,7 +226,7 @@ int power_signal_set(enum power_signal signal, int value) return ret; } -int power_signal_enable_interrupt(enum power_signal signal) +int power_signal_enable(enum power_signal signal) { const struct ps_config *cp; @@ -244,12 +244,16 @@ int power_signal_enable_interrupt(enum power_signal signal) #if HAS_GPIO_SIGNALS case PWR_SIG_SRC_GPIO: - return power_signal_gpio_enable_int(cp->src_enum); + return power_signal_gpio_enable(cp->src_enum); +#endif +#if HAS_ADC_SIGNALS + case PWR_SIG_SRC_ADC: + return power_signal_adc_enable(cp->src_enum); #endif } } -int power_signal_disable_interrupt(enum power_signal signal) +int power_signal_disable(enum power_signal signal) { const struct ps_config *cp; @@ -263,7 +267,11 @@ int power_signal_disable_interrupt(enum power_signal signal) #if HAS_GPIO_SIGNALS case PWR_SIG_SRC_GPIO: - return power_signal_gpio_disable_int(cp->src_enum); + return power_signal_gpio_disable(cp->src_enum); +#endif +#if HAS_ADC_SIGNALS + case PWR_SIG_SRC_ADC: + return power_signal_adc_disable(cp->src_enum); #endif } } diff --git a/zephyr/subsys/ap_pwrseq/signal_adc.c b/zephyr/subsys/ap_pwrseq/signal_adc.c index 9f07b73964..9898c8e4bd 100644 --- a/zephyr/subsys/ap_pwrseq/signal_adc.c +++ b/zephyr/subsys/ap_pwrseq/signal_adc.c @@ -33,42 +33,70 @@ static const struct adc_config config[] = { DT_FOREACH_STATUS_OKAY(MY_COMPAT, INIT_ADC_CONFIG) }; -static atomic_t value[ARRAY_SIZE(config)]; +/* + * Bit allocations for atomic state + */ +enum { + ADC_BIT_VALUE = 0, + ADC_BIT_LOW_ENABLED = 1, + ADC_BIT_HIGH_ENABLED = 2 +}; + +atomic_t adc_state[ARRAY_SIZE(config)]; + +static void set_trigger(const struct device *dev, + atomic_t *state, + int bit, + bool enable) +{ + /* + * Only enable or disable if the trigger is not + * already enabled or disabled. + */ + if (enable + ? !atomic_test_and_set_bit(state, bit) + : atomic_test_and_clear_bit(state, bit)) { + struct sensor_value val; + + val.val1 = enable; + sensor_attr_set(dev, + SENSOR_CHAN_VOLTAGE, + SENSOR_ATTR_ALERT, + &val); + } +} + +static void set_low_trigger(enum pwr_sig_adc adc, bool enable) +{ + set_trigger(config[adc].dev_trig_low, + &adc_state[adc], + ADC_BIT_LOW_ENABLED, + enable); + +} + +static void set_high_trigger(enum pwr_sig_adc adc, bool enable) +{ + set_trigger(config[adc].dev_trig_high, + &adc_state[adc], + ADC_BIT_HIGH_ENABLED, + enable); +} static void trigger_high(enum pwr_sig_adc adc) { - struct sensor_value val; - - atomic_set_bit(&value[adc], 0); - val.val1 = false; - sensor_attr_set(config[adc].dev_trig_high, - SENSOR_CHAN_VOLTAGE, - SENSOR_ATTR_ALERT, - &val); - val.val1 = true; - sensor_attr_set(config[adc].dev_trig_low, - SENSOR_CHAN_VOLTAGE, - SENSOR_ATTR_ALERT, - &val); + atomic_set_bit(&adc_state[adc], ADC_BIT_VALUE); + set_low_trigger(adc, true); + set_high_trigger(adc, false); LOG_DBG("power signal adc%d is HIGH", adc); power_signal_interrupt(config[adc].signal, 1); } static void trigger_low(enum pwr_sig_adc adc) { - struct sensor_value val; - - atomic_clear_bit(&value[adc], 0); - val.val1 = false; - sensor_attr_set(config[adc].dev_trig_low, - SENSOR_CHAN_VOLTAGE, - SENSOR_ATTR_ALERT, - &val); - val.val1 = true; - sensor_attr_set(config[adc].dev_trig_high, - SENSOR_CHAN_VOLTAGE, - SENSOR_ATTR_ALERT, - &val); + atomic_clear_bit(&adc_state[adc], ADC_BIT_VALUE); + set_low_trigger(adc, false); + set_high_trigger(adc, true); LOG_DBG("power signal adc%d is LOW", adc); power_signal_interrupt(config[adc].signal, 0); } @@ -78,7 +106,32 @@ int power_signal_adc_get(enum pwr_sig_adc adc) if (adc < 0 || adc >= ARRAY_SIZE(config)) { return -EINVAL; } - return !!value[adc]; + return atomic_test_bit(&adc_state[adc], ADC_BIT_VALUE); +} + +int power_signal_adc_enable(enum pwr_sig_adc adc) +{ + if (adc < 0 || adc >= ARRAY_SIZE(config)) { + return -EINVAL; + } + + /* Only need to enable relevant trigger depending on current state */ + if (atomic_test_bit(&adc_state[adc], ADC_BIT_VALUE)) { + set_low_trigger(adc, true); + } else { + set_high_trigger(adc, true); + } + return 0; +} + +int power_signal_adc_disable(enum pwr_sig_adc adc) +{ + if (adc < 0 || adc >= ARRAY_SIZE(config)) { + return -EINVAL; + } + set_low_trigger(adc, false); + set_high_trigger(adc, false); + return 0; } /* @@ -110,7 +163,6 @@ void power_signal_adc_init(void) .type = SENSOR_TRIG_THRESHOLD, .chan = SENSOR_CHAN_VOLTAGE }; - struct sensor_value val; sensor_trigger_handler_t low_cb[] = { DT_FOREACH_STATUS_OKAY_VARGS(MY_COMPAT, ADC_CB_COMMA, low) }; @@ -123,13 +175,7 @@ void power_signal_adc_init(void) /* Set high and low trigger callbacks */ sensor_trigger_set(config[i].dev_trig_high, &trig, high_cb[i]); sensor_trigger_set(config[i].dev_trig_low, &trig, low_cb[i]); - - /* Enable high trigger callback only */ - val.val1 = true; - sensor_attr_set(config[i].dev_trig_high, - SENSOR_CHAN_VOLTAGE, - SENSOR_ATTR_ALERT, - &val); + power_signal_adc_enable(i); } } diff --git a/zephyr/subsys/ap_pwrseq/signal_gpio.c b/zephyr/subsys/ap_pwrseq/signal_gpio.c index 3e940bacfd..b4888f8cff 100644 --- a/zephyr/subsys/ap_pwrseq/signal_gpio.c +++ b/zephyr/subsys/ap_pwrseq/signal_gpio.c @@ -43,7 +43,7 @@ DT_FOREACH_STATUS_OKAY(MY_COMPAT, INIT_GPIO_CONFIG) static struct gpio_callback int_cb[ARRAY_SIZE(gpio_config)]; -int power_signal_gpio_enable_int(enum pwr_sig_gpio index) +int power_signal_gpio_enable(enum pwr_sig_gpio index) { gpio_flags_t flags; @@ -65,7 +65,7 @@ int power_signal_gpio_enable_int(enum pwr_sig_gpio index) return -EINVAL; } -int power_signal_gpio_disable_int(enum pwr_sig_gpio index) +int power_signal_gpio_disable(enum pwr_sig_gpio index) { gpio_flags_t flags; @@ -141,7 +141,7 @@ void power_signal_gpio_init(void) * startup, enable the interrupt. */ if (!gpio_config[i].no_enable) { - power_signal_gpio_enable_int(i); + power_signal_gpio_enable(i); } } } diff --git a/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c b/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c index 648b46807b..34c3d5df18 100644 --- a/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c +++ b/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c @@ -4,6 +4,7 @@ */ #include <init.h> + #include <x86_non_dsx_common_pwrseq_sm_handler.h> static K_KERNEL_STACK_DEFINE(pwrseq_thread_stack, @@ -261,11 +262,13 @@ static int common_pwr_sm_run(int state) /* Notify power event that rails are up */ ap_power_ev_send_callbacks(AP_POWER_STARTUP); - /* TODO: S0ix +#if CONFIG_AP_PWRSEQ_S0IX + /* * Clearing the S0ix flag on the path to S0 * to handle any reset conditions. */ - + ap_power_reset_host_sleep_state(); +#endif return SYS_POWER_STATE_S3; case SYS_POWER_STATE_S3: @@ -289,7 +292,7 @@ static int common_pwr_sm_run(int state) /* All the power rails must be stable */ if (power_signal_get(PWR_ALL_SYS_PWRGD)) { -#if defined(CONFIG_PLATFORM_EC_CHIPSET_RESUME_INIT_HOOK) +#if CONFIG_PLATFORM_EC_CHIPSET_RESUME_INIT_HOOK /* Notify power event before resume */ ap_power_ev_send_callbacks(AP_POWER_RESUME_INIT); #endif @@ -299,13 +302,82 @@ static int common_pwr_sm_run(int state) } break; +#if CONFIG_AP_PWRSEQ_S0IX + case SYS_POWER_STATE_S0ix: + /* System in S0 only if SLP_S0 and SLP_S3 are de-asserted */ + if (power_signals_off(IN_PCH_SLP_S0) && + signals_valid_and_off(IN_PCH_SLP_S3)) { + /* TODO: Make sure ap reset handling is done + * before leaving S0ix. + */ + return SYS_POWER_STATE_S0ixS0; + } else if (!power_signals_on(IN_PGOOD_ALL_CORE)) + return SYS_POWER_STATE_S0; + + break; + + case SYS_POWER_STATE_S0S0ix: + /* + * Check sleep state and notify listeners of S0ix suspend if + * HC already set sleep suspend state. + */ + ap_power_sleep_notify_transition(AP_POWER_SLEEP_SUSPEND); + + /* + * Enable idle task deep sleep. Allow the low power idle task + * to go into deep sleep in S0ix. + */ + enable_sleep(SLEEP_MASK_AP_RUN); + +#if CONFIG_PLATFORM_EC_CHIPSET_RESUME_INIT_HOOK + ap_power_ev_send_callbacks(AP_POWER_SUSPEND_COMPLETE); +#endif + + return SYS_POWER_STATE_S0ix; + + case SYS_POWER_STATE_S0ixS0: + if (power_get_host_sleep_state() != + HOST_SLEEP_EVENT_S0IX_RESUME) + break; + + /* + * Disable idle task deep sleep. This means that the low + * power idle task will not go into deep sleep while in S0. + */ + disable_sleep(SLEEP_MASK_AP_RUN); + +#if CONFIG_PLATFORM_EC_CHIPSET_RESUME_INIT_HOOK + ap_power_ev_send_callbacks(AP_POWER_RESUME_INIT); +#endif + + return SYS_POWER_STATE_S0; + +#endif /* CONFIG_AP_PWRSEQ_S0IX */ + case SYS_POWER_STATE_S0: if (!power_signals_on(IN_PGOOD_ALL_CORE)) { ap_power_force_shutdown(AP_POWER_SHUTDOWN_POWERFAIL); return SYS_POWER_STATE_G3; - } else if (signals_valid_and_on(IN_PCH_SLP_S3)) + } else if (signals_valid_and_on(IN_PCH_SLP_S3)) { return SYS_POWER_STATE_S0S3; - /* TODO: S0ix */ + +#if CONFIG_AP_PWRSEQ_S0IX + /* + * SLP_S0 may assert in system idle scenario without a kernel + * freeze call. This may cause interrupt storm since there is + * no freeze/unfreeze of threads/process in the idle scenario. + * Ignore the SLP_S0 assertions in idle scenario by checking + * the host sleep state. + */ + } else if (power_get_host_sleep_state() + == HOST_SLEEP_EVENT_S0IX_SUSPEND && + power_signals_on(IN_PCH_SLP_S0)) { + + return SYS_POWER_STATE_S0S0ix; + } else { + ap_power_sleep_notify_transition(AP_POWER_SLEEP_RESUME); +#endif /* CONFIG_AP_PWRSEQ_S0IX */ + } break; @@ -325,6 +397,9 @@ static int common_pwr_sm_run(int state) * correctly handle global resets which have a bit of delay * while the SLP_Sx_L signals are asserted then deasserted. */ + /* TODO */ + /* power_s5_up = 0; */ + return SYS_POWER_STATE_S5; case SYS_POWER_STATE_S3S4: @@ -333,10 +408,22 @@ static int common_pwr_sm_run(int state) case SYS_POWER_STATE_S0S3: /* Notify power event before we remove power rails */ ap_power_ev_send_callbacks(AP_POWER_SUSPEND); -#if defined(CONFIG_PLATFORM_EC_CHIPSET_RESUME_INIT_HOOK) +#if CONFIG_PLATFORM_EC_CHIPSET_RESUME_INIT_HOOK /* Notify power event after suspend */ ap_power_ev_send_callbacks(AP_POWER_SUSPEND_COMPLETE); #endif + + /* + * Enable idle task deep sleep. Allow the low power idle task + * to go into deep sleep in S3 or lower. + */ + enable_sleep(SLEEP_MASK_AP_RUN); + +#if CONFIG_AP_PWRSEQ_S0IX + /* Re-initialize S0ix flag */ + ap_power_reset_host_sleep_state(); +#endif + return SYS_POWER_STATE_S3; default: @@ -386,8 +473,10 @@ static void pwrseq_loop_thread(void *p1, void *p2, void *p3) if (curr_state == new_state) new_state = common_pwr_sm_run(curr_state); - if (curr_state != new_state) + if (curr_state != new_state) { pwr_sm_set_state(new_state); + ap_power_set_active_wake_mask(); + } k_msleep(t_wait_ms); } diff --git a/zephyr/test/.pylintrc b/zephyr/test/.pylintrc new file mode 100644 index 0000000000..9ca0b5f8c9 --- /dev/null +++ b/zephyr/test/.pylintrc @@ -0,0 +1,21 @@ +[MASTER] +init-hook='import sys; sys.path.append("/usr/lib64/python3.6/site-packages")' + +[MESSAGES CONTROL] + +disable=bad-continuation,bad-whitespace,format,fixme + +[format] + +max-line-length=88 +string-quote=double + +[BASIC] +additional-builtins= + here, + register_binman_project, + register_host_project, + register_host_test, + register_npcx_project, + register_raw_project, +good-names=BUILD diff --git a/zephyr/test/accel_cal/BUILD.py b/zephyr/test/accel_cal/BUILD.py index bb50fd4301..8c743bf48b 100644 --- a/zephyr/test/accel_cal/BUILD.py +++ b/zephyr/test/accel_cal/BUILD.py @@ -2,4 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Register zmake project for accel_cal test.""" + register_host_test("accel_cal") diff --git a/zephyr/test/ap_power/BUILD.py b/zephyr/test/ap_power/BUILD.py index f511b313ef..e3dac8c77e 100644 --- a/zephyr/test/ap_power/BUILD.py +++ b/zephyr/test/ap_power/BUILD.py @@ -2,4 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Register zmake project for ap_power test.""" + register_host_test("ap_power", dts_overlays=["overlay.dts"]) diff --git a/zephyr/test/ap_power/prj.conf b/zephyr/test/ap_power/prj.conf index 0cc677e3e7..86c3f5082d 100644 --- a/zephyr/test/ap_power/prj.conf +++ b/zephyr/test/ap_power/prj.conf @@ -45,6 +45,7 @@ CONFIG_X86_NON_DSX_PWRSEQ_ADL=y CONFIG_AP_X86_INTEL_ADL=y CONFIG_PLATFORM_EC_ESPI_VW_SLP_S4=y CONFIG_PLATFORM_EC_ESPI_VW_SLP_S5=y +CONFIG_AP_PWRSEQ_STACK_SIZE=1024 CONFIG_ESPI=y CONFIG_ESPI_EMUL=y diff --git a/zephyr/test/ap_power/src/signals.c b/zephyr/test/ap_power/src/signals.c index 432b28042b..debd459807 100644 --- a/zephyr/test/ap_power/src/signals.c +++ b/zephyr/test/ap_power/src/signals.c @@ -97,26 +97,26 @@ ZTEST(signals, test_validate_request) zassert_equal(-EINVAL, power_signal_set(PWR_SLP_S0, 1), "power_signal_set on input pin should not succeed"); /* Can't enable interrupt on output */ - zassert_equal(-EINVAL, power_signal_enable_interrupt(PWR_VCCST_PWRGD), + zassert_equal(-EINVAL, power_signal_enable(PWR_VCCST_PWRGD), "enable interrupt on output pin should not succeed"); /* Can't disable interrupt on output */ - zassert_equal(-EINVAL, power_signal_disable_interrupt(PWR_VCCST_PWRGD), + zassert_equal(-EINVAL, power_signal_disable(PWR_VCCST_PWRGD), "disable interrupt on output pin should not succeed"); /* Can't enable interrupt on input with no interrupt flags */ - zassert_equal(-EINVAL, power_signal_enable_interrupt(PWR_IMVP9_VRRDY), + zassert_equal(-EINVAL, power_signal_enable(PWR_IMVP9_VRRDY), "enable interrupt on input pin without interrupt config"); /* Can't disable interrupt on input with no interrupt flags */ zassert_equal(-EINVAL, - power_signal_disable_interrupt(PWR_IMVP9_VRRDY), + power_signal_disable(PWR_IMVP9_VRRDY), "disable interrupt on input pin without interrupt config"); /* Invalid signal - should be rejectde */ zassert_equal(-EINVAL, power_signal_get(-1), "power_signal_get with -1 signal should fail"); zassert_equal(-EINVAL, power_signal_set(-1, 1), "power_signal_set with -1 signal should fail"); - zassert_equal(-EINVAL, power_signal_enable_interrupt(-1), + zassert_equal(-EINVAL, power_signal_enable(-1), "enable interrupt with -1 signal should fail"); - zassert_equal(-EINVAL, power_signal_disable_interrupt(-1), + zassert_equal(-EINVAL, power_signal_disable(-1), "disable interrupt with -1 signal should fail"); } @@ -359,7 +359,7 @@ ZTEST(signals, test_gpio_interrupts) zassert_equal(false, power_signals_on(s0), "SLP_S0 should not have updated"); - power_signal_enable_interrupt(PWR_SLP_S0); + power_signal_enable(PWR_SLP_S0); emul_set(PWR_SLP_S0, 0); zassert_equal(true, power_signals_on(s0), "SLP_S0 should have updated the mask"); @@ -370,7 +370,7 @@ ZTEST(signals, test_gpio_interrupts) /* * Disable the GPIO interrupt again. */ - power_signal_disable_interrupt(PWR_SLP_S0); + power_signal_disable(PWR_SLP_S0); emul_set(PWR_SLP_S0, 0); zassert_equal(false, power_signals_on(s0), "SLP_S0 should not have updated the mask"); diff --git a/zephyr/test/base32/BUILD.py b/zephyr/test/base32/BUILD.py index 67e7c50089..28023ccdc9 100644 --- a/zephyr/test/base32/BUILD.py +++ b/zephyr/test/base32/BUILD.py @@ -2,4 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Register zmake project for base32 test.""" + register_host_test("base32") diff --git a/zephyr/test/crc/BUILD.py b/zephyr/test/crc/BUILD.py index 17136be0ce..8ca9c04936 100644 --- a/zephyr/test/crc/BUILD.py +++ b/zephyr/test/crc/BUILD.py @@ -2,4 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Register zmake project for crc test.""" + register_host_test("crc") diff --git a/zephyr/test/drivers/BUILD.py b/zephyr/test/drivers/BUILD.py index 1653103526..04449e2f8e 100644 --- a/zephyr/test/drivers/BUILD.py +++ b/zephyr/test/drivers/BUILD.py @@ -2,4 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Register zmake project for drivers test.""" + register_host_test("drivers", dts_overlays=["overlay.dts"]) diff --git a/zephyr/test/drivers/include/test/drivers/utils.h b/zephyr/test/drivers/include/test/drivers/utils.h index 6d5d0c33bf..c8258af6f7 100644 --- a/zephyr/test/drivers/include/test/drivers/utils.h +++ b/zephyr/test/drivers/include/test/drivers/utils.h @@ -227,6 +227,42 @@ void host_cmd_motion_sense_dump(int max_sensor_count, struct ec_response_motion_sense *response); /** + * @brief Call the host command MOTION_SENSE with the data sub-command + * + * @param sensor_num The sensor index in the motion_sensors array to query + * @param response Pointer to the response data structure to fill on success + * @return The result code from the host command + */ +int host_cmd_motion_sense_data(uint8_t sensor_num, + struct ec_response_motion_sense *response); + +/** + * @brief Call the host command MOTION_SENSE with the info sub-command + * + * @param cmd_version The command version + * @param sensor_num The sensor index in the motion_sensors array to query + * @param response Pointer to the response data structure to fill on success + * @return The result code from the host command + */ +int host_cmd_motion_sense_info(uint8_t cmd_version, uint8_t sensor_num, + struct ec_response_motion_sense *response); + +/** + * @brief Call the host command MOTION_SENSE with the ec_rate sub-command + * + * This function performs a read of the current rate by passing + * EC_MOTION_SENSE_NO_VALUE as the data rate. Otherwise, the data rate should be + * updated. + * + * @param sensor_num The sensor index in the motion_sensors array to query + * @param data_rate_ms The new data rate or EC_MOTION_SENSE_NO_VALUE to read + * @param response Pointer to the response data structure to fill on success + * @return The result code from the host command + */ +int host_cmd_motion_sense_ec_rate(uint8_t sensor_num, int data_rate_ms, + struct ec_response_motion_sense *response); + +/** * Run the host command to get the PD discovery responses. * * @param port The USB-C port number diff --git a/zephyr/test/drivers/src/host_cmd/motion_sense.c b/zephyr/test/drivers/src/host_cmd/motion_sense.c index 3e4c8e0336..4063007401 100644 --- a/zephyr/test/drivers/src/host_cmd/motion_sense.c +++ b/zephyr/test/drivers/src/host_cmd/motion_sense.c @@ -16,8 +16,13 @@ (sizeof(struct ec_response_motion_sense) + \ n * sizeof(struct ec_response_motion_sensor_data)) -ZTEST_SUITE(host_cmd_motion_sense, drivers_predicate_post_main, NULL, NULL, - NULL, NULL); +static void host_cmd_motion_sense_before(void *state) +{ + motion_sensors[0].config[SENSOR_CONFIG_AP].ec_rate = 1000 * MSEC; +} + +ZTEST_SUITE(host_cmd_motion_sense, drivers_predicate_post_main, NULL, + host_cmd_motion_sense_before, NULL, NULL); ZTEST_USER(host_cmd_motion_sense, test_dump) { @@ -64,3 +69,124 @@ ZTEST_USER(host_cmd_motion_sense, test_dump__large_max_sensor_count) zassert_equal(result->dump.sensor_count, ALL_MOTION_SENSORS, NULL); } + +ZTEST_USER(host_cmd_motion_sense, test_read_data__invalid_sensor_num) +{ + struct ec_response_motion_sense response; + + zassert_equal(host_cmd_motion_sense_data(UINT8_MAX, &response), + EC_RES_INVALID_PARAM, NULL); +} + +ZTEST_USER(host_cmd_motion_sense, test_read_data) +{ + struct ec_response_motion_sense response; + + motion_sensors[0].xyz[0] = 1; + motion_sensors[0].xyz[1] = 2; + motion_sensors[0].xyz[2] = 3; + + zassert_ok(host_cmd_motion_sense_data(0, &response), NULL); + zassert_equal(response.data.flags, 0, NULL); + zassert_equal(response.data.data[0], 1, NULL); + zassert_equal(response.data.data[1], 2, NULL); + zassert_equal(response.data.data[2], 3, NULL); +} + +ZTEST_USER(host_cmd_motion_sense, test_get_info__invalid_sensor_num) +{ + struct ec_response_motion_sense response; + + zassert_equal(host_cmd_motion_sense_info(/*cmd_version=*/1, + /*sensor_num=*/UINT8_MAX, + &response), + EC_RES_INVALID_PARAM, NULL); +} + +ZTEST_USER(host_cmd_motion_sense, test_get_info_v1) +{ + struct ec_response_motion_sense response; + + zassert_ok(host_cmd_motion_sense_info(/*cmd_version=*/1, + /*sensor_num=*/0, &response), + NULL); + zassert_equal(response.info.type, motion_sensors[0].type, NULL); + zassert_equal(response.info.location, motion_sensors[0].location, NULL); + zassert_equal(response.info.chip, motion_sensors[0].chip, NULL); +} + +ZTEST_USER(host_cmd_motion_sense, test_get_info_v3) +{ + struct ec_response_motion_sense response; + + zassert_ok(host_cmd_motion_sense_info(/*cmd_version=*/3, + /*sensor_num=*/0, &response), + NULL); + zassert_equal(response.info.type, motion_sensors[0].type, NULL); + zassert_equal(response.info.location, motion_sensors[0].location, NULL); + zassert_equal(response.info.chip, motion_sensors[0].chip, NULL); + zassert_equal(response.info_3.min_frequency, + motion_sensors[0].min_frequency, NULL); + zassert_equal(response.info_3.max_frequency, + motion_sensors[0].max_frequency, NULL); + zassert_equal(response.info_3.fifo_max_event_count, + CONFIG_ACCEL_FIFO_SIZE, NULL); +} + +ZTEST_USER(host_cmd_motion_sense, test_get_info_v4__no_read_temp) +{ + struct ec_response_motion_sense response; + + zassert_ok(host_cmd_motion_sense_info(/*cmd_version=*/4, + /*sensor_num=*/0, &response), + NULL); + zassert_equal(response.info.type, motion_sensors[0].type, NULL); + zassert_equal(response.info.location, motion_sensors[0].location, NULL); + zassert_equal(response.info.chip, motion_sensors[0].chip, NULL); + if (IS_ENABLED(CONFIG_ONLINE_CALIB)) { + zassert_true(response.info_4.flags & + MOTION_SENSE_CMD_INFO_FLAG_ONLINE_CALIB, + NULL); + } else { + zassert_false(response.info_4.flags & + MOTION_SENSE_CMD_INFO_FLAG_ONLINE_CALIB, + NULL); + } +} + +ZTEST_USER(host_cmd_motion_sense, test_get_ec_rate__invalid_sensor_num) +{ + struct ec_response_motion_sense response; + + zassert_equal(host_cmd_motion_sense_ec_rate( + /*sensor_num=*/0xff, + /*data_rate_ms=*/EC_MOTION_SENSE_NO_VALUE, + &response), + EC_RES_INVALID_PARAM, NULL); +} + +ZTEST_USER(host_cmd_motion_sense, test_get_ec_rate) +{ + struct ec_response_motion_sense response; + + zassert_ok(host_cmd_motion_sense_ec_rate( + /*sensor_num=*/0, + /*data_rate_ms=*/EC_MOTION_SENSE_NO_VALUE, + &response), + NULL); + zassert_equal(response.ec_rate.ret, 1000, NULL); +} + +ZTEST_USER(host_cmd_motion_sense, test_set_ec_rate) +{ + struct ec_response_motion_sense response; + + zassert_ok(host_cmd_motion_sense_ec_rate( + /*sensor_num=*/0, /*data_rate_ms=*/2000, &response), + NULL); + /* The command should return the previous rate */ + zassert_equal(response.ec_rate.ret, 1000, NULL); + /* The sensor's AP config value should be updated */ + zassert_equal(motion_sensors[0].config[SENSOR_CONFIG_AP].ec_rate, + 2000 * MSEC, NULL); +} diff --git a/zephyr/test/drivers/src/integration/usbc/usb_5v_3a_pd_sink.c b/zephyr/test/drivers/src/integration/usbc/usb_5v_3a_pd_sink.c index 9541f20dd3..9a4df7d11e 100644 --- a/zephyr/test/drivers/src/integration/usbc/usb_5v_3a_pd_sink.c +++ b/zephyr/test/drivers/src/integration/usbc/usb_5v_3a_pd_sink.c @@ -34,7 +34,10 @@ connect_sink_to_port(struct usb_attach_5v_3a_pd_sink_fixture *fixture) TCPC_REG_POWER_STATUS_VBUS_DET); tcpci_emul_set_reg(fixture->tcpci_emul, TCPC_REG_EXT_STATUS, TCPC_REG_EXT_STATUS_SAFE0V); + tcpci_tcpc_alert(0); + k_sleep(K_SECONDS(1)); + zassume_ok(tcpci_snk_emul_connect_to_tcpci( &fixture->sink_5v_3a.data, &fixture->sink_5v_3a.common_data, diff --git a/zephyr/test/drivers/src/integration/usbc/usb_attach_src_snk.c b/zephyr/test/drivers/src/integration/usbc/usb_attach_src_snk.c index 4ed9dcb8d1..54598c4685 100644 --- a/zephyr/test/drivers/src/integration/usbc/usb_attach_src_snk.c +++ b/zephyr/test/drivers/src/integration/usbc/usb_attach_src_snk.c @@ -769,13 +769,13 @@ ZTEST_F(usb_detach_test, verify_detach_sink) ZTEST_F(usb_detach_test, verify_detach_source) { struct emul_state *fixture = &this->fixture; - struct ec_response_usb_pd_power_info pd_power_info = { 0 }; + struct ec_response_usb_pd_power_info pd_power_info = { SNK_PORT }; integration_usb_test_source_detach(fixture); k_sleep(K_SECONDS(10)); isl923x_emul_set_adc_vbus(fixture->charger_isl923x_emul, 0); - pd_power_info = host_cmd_power_info(SRC_PORT); + pd_power_info = host_cmd_power_info(SNK_PORT); /* Assert */ zassert_equal(pd_power_info.role, USB_PD_PORT_POWER_DISCONNECTED, diff --git a/zephyr/test/drivers/src/utils.c b/zephyr/test/drivers/src/utils.c index ef2084ab07..a639b63d17 100644 --- a/zephyr/test/drivers/src/utils.c +++ b/zephyr/test/drivers/src/utils.c @@ -112,6 +112,53 @@ void host_cmd_motion_sense_dump(int max_sensor_count, "Failed to get motion_sense dump"); } +int host_cmd_motion_sense_data(uint8_t sensor_num, + struct ec_response_motion_sense *response) +{ + struct ec_params_motion_sense params = { + .cmd = MOTIONSENSE_CMD_DATA, + .sensor_odr = { + .sensor_num = sensor_num, + }, + }; + struct host_cmd_handler_args args = BUILD_HOST_COMMAND( + EC_CMD_MOTION_SENSE_CMD, 4, *response, params); + + return host_command_process(&args); +} + +int host_cmd_motion_sense_info(uint8_t cmd_version, uint8_t sensor_num, + struct ec_response_motion_sense *response) +{ + struct ec_params_motion_sense params = { + .cmd = MOTIONSENSE_CMD_INFO, + .sensor_odr = { + .sensor_num = sensor_num, + }, + }; + struct host_cmd_handler_args args = BUILD_HOST_COMMAND( + EC_CMD_MOTION_SENSE_CMD, cmd_version, *response, params); + + return host_command_process(&args); +} + +int host_cmd_motion_sense_ec_rate(uint8_t sensor_num, int data_rate_ms, + struct ec_response_motion_sense *response) +{ + struct ec_params_motion_sense params = { + .cmd = MOTIONSENSE_CMD_EC_RATE, + .ec_rate = { + .sensor_num = sensor_num, + .data = data_rate_ms, + }, + }; + struct host_cmd_handler_args args = BUILD_HOST_COMMAND( + EC_CMD_MOTION_SENSE_CMD, 1, *response, params); + + printk("sensor_num=%u/%u\n", params.sensor_odr.sensor_num, sensor_num); + return host_command_process(&args); +} + void host_cmd_typec_discovery(int port, enum typec_partner_type partner_type, void *response, size_t response_size) { diff --git a/zephyr/test/ec_app/BUILD.py b/zephyr/test/ec_app/BUILD.py index 48d072fe19..eeb85c0e46 100644 --- a/zephyr/test/ec_app/BUILD.py +++ b/zephyr/test/ec_app/BUILD.py @@ -2,4 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Register zmake project for ec_app test.""" + register_host_test("ec_app") diff --git a/zephyr/test/hooks/BUILD.py b/zephyr/test/hooks/BUILD.py index 6b20daea30..ee25ae52bc 100644 --- a/zephyr/test/hooks/BUILD.py +++ b/zephyr/test/hooks/BUILD.py @@ -2,4 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Register zmake project for hooks test.""" + register_host_test("hooks") diff --git a/zephyr/test/i2c/BUILD.py b/zephyr/test/i2c/BUILD.py index 150926dc69..86d9da537a 100644 --- a/zephyr/test/i2c/BUILD.py +++ b/zephyr/test/i2c/BUILD.py @@ -2,4 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Register zmake project for i2c test.""" + register_host_test("i2c", dts_overlays=["overlay.dts"]) diff --git a/zephyr/test/i2c_dts/BUILD.py b/zephyr/test/i2c_dts/BUILD.py index ec93d8b6f7..e0e97be121 100644 --- a/zephyr/test/i2c_dts/BUILD.py +++ b/zephyr/test/i2c_dts/BUILD.py @@ -2,4 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Register zmake project for i2c_dts test.""" + register_host_test("i2c_dts", dts_overlays=["overlay.dts"]) diff --git a/zephyr/test/math/BUILD.py b/zephyr/test/math/BUILD.py index 2b624b1bdd..8f6b28ce1a 100644 --- a/zephyr/test/math/BUILD.py +++ b/zephyr/test/math/BUILD.py @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Register zmake project for math tests.""" + register_host_test( "math_fixed", kconfig_files=[here / "prj.conf", here / "fixed_point.conf"] ) diff --git a/zephyr/test/system/BUILD.py b/zephyr/test/system/BUILD.py index 1aecdeb37d..b9f14c2fcf 100644 --- a/zephyr/test/system/BUILD.py +++ b/zephyr/test/system/BUILD.py @@ -2,4 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Register zmake project for system test.""" + register_host_test("system", dts_overlays=["overlay.dts"]) diff --git a/zephyr/test/tasks/BUILD.py b/zephyr/test/tasks/BUILD.py index 1f49d4b41d..9280101836 100644 --- a/zephyr/test/tasks/BUILD.py +++ b/zephyr/test/tasks/BUILD.py @@ -2,4 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Register zmake project for tasks test.""" + register_host_test("tasks") diff --git a/zephyr/zmake/.pylintrc b/zephyr/zmake/.pylintrc index 341cb4d687..fd798870dd 100644 --- a/zephyr/zmake/.pylintrc +++ b/zephyr/zmake/.pylintrc @@ -1,9 +1,9 @@ [MASTER] -init-hook='import sys; sys.path.append("/usr/lib64/python3.6/site-packages")' +init-hook='import sys; sys.path.extend(["zephyr/zmake", "/usr/lib64/python3.6/site-packages"])' [MESSAGES CONTROL] -disable=bad-continuation,bad-whitespace,format,fixme +disable=bad-continuation,bad-whitespace,format,fixme,wrong-import-order [format] diff --git a/zephyr/zmake/README.md b/zephyr/zmake/README.md index 12125d8213..6e2690959b 100644 --- a/zephyr/zmake/README.md +++ b/zephyr/zmake/README.md @@ -85,7 +85,7 @@ Chromium OS's meta-build tool for Zephyr ### zmake list-projects -**Usage:** `zmake list-projects [-h] [--format FORMAT] [search_dir]` +**Usage:** `zmake list-projects [-h] [--format FMT] [search_dir]` #### Positional Arguments @@ -98,7 +98,7 @@ Chromium OS's meta-build tool for Zephyr | | | |---|---| | `-h`, `--help` | show this help message and exit | -| `--format FORMAT` | Output format to print projects (str.format(config=project.config) is called on this for each project). | +| `--format FMT` | Output format to print projects (str.format(config=project.config) is called on this for each project). | ### zmake test diff --git a/zephyr/zmake/tests/test_build_config.py b/zephyr/zmake/tests/test_build_config.py index aab41b84ef..76cc0a2028 100644 --- a/zephyr/zmake/tests/test_build_config.py +++ b/zephyr/zmake/tests/test_build_config.py @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Tests of zmake's build config system.""" + import argparse import os import pathlib @@ -16,6 +18,8 @@ import zmake.jobserver import zmake.util as util from zmake.build_config import BuildConfig +# pylint:disable=redefined-outer-name,unused-argument + # Strategies for use with hypothesis filenames = st.text( alphabet=set(string.printable) - {"/", ";"}, min_size=1, max_size=254 @@ -71,13 +75,13 @@ def test_merge(coins, combined): kconf1, kconf2 = split(combined.kconfig_defs.items()) files1, files2 = split(combined.kconfig_files) - c1 = BuildConfig( + config1 = BuildConfig( environ_defs=dict(env1), cmake_defs=dict(cmake1), kconfig_defs=dict(kconf1), kconfig_files=files1, ) - c2 = BuildConfig( + config2 = BuildConfig( environ_defs=dict(env2), cmake_defs=dict(cmake2), kconfig_defs=dict(kconf2), @@ -85,7 +89,7 @@ def test_merge(coins, combined): ) # Merge the split configs - merged = c1 | c2 + merged = config1 | config2 # Assert that the merged split configs is the original config assert merged.environ_defs == combined.environ_defs @@ -104,9 +108,10 @@ class FakeJobClient(zmake.jobserver.JobClient): def get_job(self): return zmake.jobserver.JobHandle(lambda: None) - def popen(self, argv, env={}, **kwargs): + def popen(self, argv, **kwargs): + kwargs.setdefault("env", {}) self.captured_argv = [str(arg) for arg in argv] - self.captured_env = {str(k): str(v) for k, v in env.items()} + self.captured_env = {str(k): str(v) for k, v in kwargs["env"].items()} def parse_cmake_args(argv): @@ -145,12 +150,12 @@ def parse_cmake_args(argv): @hypothesis.given(build_configs_no_kconfig, paths, paths) @hypothesis.settings(deadline=60000) -def test_popen_cmake_no_kconfig(conf, project_dir, build_dir): +def test_popen_cmake_no_kconfig(conf: BuildConfig, project_dir, build_dir): """Test popen_cmake for a config with no kconfig definitions.""" job_client = FakeJobClient() conf.popen_cmake(job_client, project_dir, build_dir) - args, cmake_defs = parse_cmake_args(job_client.captured_argv) + _, cmake_defs = parse_cmake_args(job_client.captured_argv) assert cmake_defs == conf.cmake_defs assert job_client.captured_env == conf.environ_defs @@ -158,7 +163,7 @@ def test_popen_cmake_no_kconfig(conf, project_dir, build_dir): @hypothesis.given(build_configs_with_at_least_one_kconfig, paths, paths) @hypothesis.settings(deadline=60000) -def test_popen_cmake_kconfig_but_no_file(conf, project_dir, build_dir): +def test_popen_cmake_kconfig_but_no_file(conf: BuildConfig, project_dir, build_dir): """Test that running popen_cmake with Kconfig definitions to write out, but no path to do so, should raise an error. """ @@ -170,18 +175,19 @@ def test_popen_cmake_kconfig_but_no_file(conf, project_dir, build_dir): @hypothesis.given(build_configs, paths, paths) @hypothesis.settings(deadline=60000) -def test_popen_cmake_kconfig(conf, project_dir, build_dir): +def test_popen_cmake_kconfig(conf: BuildConfig, project_dir, build_dir): + """Test calling popen_cmake and verifying the kconfig_files.""" job_client = FakeJobClient() - with tempfile.NamedTemporaryFile("w", delete=False) as f: - temp_path = f.name + with tempfile.NamedTemporaryFile("w", delete=False) as file: + temp_path = file.name try: conf.popen_cmake( job_client, project_dir, build_dir, kconfig_path=pathlib.Path(temp_path) ) - args, cmake_defs = parse_cmake_args(job_client.captured_argv) + _, cmake_defs = parse_cmake_args(job_client.captured_argv) expected_kconfig_files = set(str(f) for f in conf.kconfig_files) expected_kconfig_files.add(temp_path) @@ -215,9 +221,10 @@ def fake_kconfig_files(tmp_path): def test_build_config_json_stability(fake_kconfig_files): - # as_json() should return equivalent strings for two equivalent - # build configs. - a = BuildConfig( + """as_json() should return equivalent strings for two equivalent + build configs. + """ + config_a = BuildConfig( environ_defs={ "A": "B", "B": "C", @@ -234,7 +241,7 @@ def test_build_config_json_stability(fake_kconfig_files): ) # Dict ordering is intentionally reversed in b. - b = BuildConfig( + config_b = BuildConfig( environ_defs={ "B": "C", "A": "B", @@ -250,20 +257,21 @@ def test_build_config_json_stability(fake_kconfig_files): kconfig_files=list(fake_kconfig_files), ) - assert a.as_json() == b.as_json() + assert config_a.as_json() == config_b.as_json() def test_build_config_json_inequality(): - # Two differing build configs should not have the same json - # representation. - a = BuildConfig(cmake_defs={"A": "B"}) - b = BuildConfig(environ_defs={"A": "B"}) + """Two differing build configs should not have the same json + representation. + """ + config_a = BuildConfig(cmake_defs={"A": "B"}) + config_b = BuildConfig(environ_defs={"A": "B"}) - assert a.as_json() != b.as_json() + assert config_a.as_json() != config_b.as_json() def test_build_config_json_inequality_dtc_changes(tmp_path): - # When DTC overlay files change, so should the JSON. + """When DTC overlay files change, so should the JSON.""" dts_file_1 = tmp_path / "overlay1.dts" dts_file_1.write_text("/* blah */\n") @@ -287,8 +295,8 @@ def test_build_config_json_inequality_dtc_changes(tmp_path): def test_kconfig_file_duplicates(fake_kconfig_files): - # Kconfig files should be like the "uniq" command. Repeats should - # be removed, but not duplicates. + """Kconfig files should be like the "uniq" command. Repeats should + be removed, but not duplicates.""" cfg = BuildConfig( kconfig_files=[ fake_kconfig_files[0], diff --git a/zephyr/zmake/tests/test_modules.py b/zephyr/zmake/tests/test_modules.py index 87e5d7bfc9..600544d2e7 100644 --- a/zephyr/zmake/tests/test_modules.py +++ b/zephyr/zmake/tests/test_modules.py @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Test zmake modules module.""" + import pathlib import tempfile diff --git a/zephyr/zmake/tests/test_multiproc_executor.py b/zephyr/zmake/tests/test_multiproc_executor.py index ebc2be5e4f..c905ef03ec 100644 --- a/zephyr/zmake/tests/test_multiproc_executor.py +++ b/zephyr/zmake/tests/test_multiproc_executor.py @@ -1,52 +1,62 @@ # 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. + +"""Tests for zmake multiproc.""" + import threading import zmake.multiproc def test_single_function_executor_success(): + """Test single function success.""" executor = zmake.multiproc.Executor() executor.append(lambda: 0) assert executor.wait() == 0 def test_single_function_executor_fail(): + """Test single function fail.""" executor = zmake.multiproc.Executor() executor.append(lambda: -2) assert executor.wait() == -2 def test_single_function_executor_raise(): + """Test single function raising an exception.""" executor = zmake.multiproc.Executor() executor.append(lambda: 1 / 0) assert executor.wait() != 0 -def _lock_step(cv, predicate, step, return_value=0): - with cv: - cv.wait_for(predicate=lambda: step[0] == predicate) +def _lock_step(cond, predicate, step, return_value=0): + with cond: + cond.wait_for(predicate=lambda: step[0] == predicate) step[0] += 1 - cv.notify_all() + cond.notify_all() return return_value def test_two_function_executor_wait_for_both(): - cv = threading.Condition() + """Test two functions in executor.""" + cond = threading.Condition() step = [0] executor = zmake.multiproc.Executor() - executor.append(lambda: _lock_step(cv=cv, predicate=0, step=step)) - executor.append(lambda: _lock_step(cv=cv, predicate=1, step=step)) + executor.append(lambda: _lock_step(cond=cond, predicate=0, step=step)) + executor.append(lambda: _lock_step(cond=cond, predicate=1, step=step)) assert executor.wait() == 0 assert step[0] == 2 def test_two_function_executor_one_fails(): - cv = threading.Condition() + """Test two functions in executor, when one fails.""" + cond = threading.Condition() step = [0] executor = zmake.multiproc.Executor() - executor.append(lambda: _lock_step(cv=cv, predicate=0, step=step, return_value=-1)) - executor.append(lambda: _lock_step(cv=cv, predicate=1, step=step)) + executor.append( + lambda: _lock_step(cond=cond, predicate=0, step=step, return_value=-1) + ) + executor.append(lambda: _lock_step(cond=cond, predicate=1, step=step)) assert executor.wait() == -1 assert step[0] == 2 diff --git a/zephyr/zmake/tests/test_multiproc_logging.py b/zephyr/zmake/tests/test_multiproc_logging.py index 2eac9326d3..2694b6451e 100644 --- a/zephyr/zmake/tests/test_multiproc_logging.py +++ b/zephyr/zmake/tests/test_multiproc_logging.py @@ -1,6 +1,9 @@ # 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. + +"""Tests for zmake multiproc logging code.""" + import io import logging import os @@ -11,30 +14,32 @@ import zmake.multiproc def test_read_output_from_pipe(): + """Test reading output from a pipe.""" semaphore = threading.Semaphore(0) pipe = os.pipe() - fd = io.TextIOWrapper(os.fdopen(pipe[0], "rb"), encoding="utf-8") + file_desc = io.TextIOWrapper(os.fdopen(pipe[0], "rb"), encoding="utf-8") logger = mock.Mock(spec=logging.Logger) logger.log.side_effect = lambda log_lvl, line: semaphore.release() - zmake.multiproc.log_output(logger, logging.DEBUG, fd, job_id="") + zmake.multiproc.LogWriter.log_output(logger, logging.DEBUG, file_desc, job_id="") os.write(pipe[1], "Hello\n".encode("utf-8")) semaphore.acquire() logger.log.assert_called_with(logging.DEBUG, "Hello") def test_read_output_change_log_level(): + """Test changing the log level.""" semaphore = threading.Semaphore(0) pipe = os.pipe() - fd = io.TextIOWrapper(os.fdopen(pipe[0], "rb"), encoding="utf-8") + file_desc = io.TextIOWrapper(os.fdopen(pipe[0], "rb"), encoding="utf-8") logger = mock.Mock(spec=logging.Logger) logger.log.side_effect = lambda log_lvl, line: semaphore.release() # This call will log output from fd (the file descriptor) to DEBUG, though # when the line starts with 'World', the logging level will be switched to # CRITICAL (see the content of the log_lvl_override_func). - zmake.multiproc.log_output( + zmake.multiproc.LogWriter.log_output( logger=logger, log_level=logging.DEBUG, - file_descriptor=fd, + file_descriptor=file_desc, log_level_override_func=lambda line, lvl: logging.CRITICAL if line.startswith("World") else lvl, @@ -72,8 +77,8 @@ def test_read_output_from_second_pipe(): logger = mock.Mock(spec=logging.Logger) logger.log.side_effect = lambda log_lvl, fmt, id, line: semaphore.release() - zmake.multiproc.log_output(logger, logging.DEBUG, fds[0], job_id="0") - zmake.multiproc.log_output(logger, logging.ERROR, fds[1], job_id="1") + zmake.multiproc.LogWriter.log_output(logger, logging.DEBUG, fds[0], job_id="0") + zmake.multiproc.LogWriter.log_output(logger, logging.ERROR, fds[1], job_id="1") os.write(pipes[1][1], "Hello\n".encode("utf-8")) semaphore.acquire() @@ -97,8 +102,8 @@ def test_read_output_after_another_pipe_closed(): logger = mock.Mock(spec=logging.Logger) logger.log.side_effect = lambda log_lvl, fmt, id, line: semaphore.release() - zmake.multiproc.log_output(logger, logging.DEBUG, fds[0], job_id="0") - zmake.multiproc.log_output(logger, logging.ERROR, fds[1], job_id="1") + zmake.multiproc.LogWriter.log_output(logger, logging.DEBUG, fds[0], job_id="0") + zmake.multiproc.LogWriter.log_output(logger, logging.ERROR, fds[1], job_id="1") fds[0].close() os.write(pipes[1][1], "Hello\n".encode("utf-8")) diff --git a/zephyr/zmake/tests/test_packers.py b/zephyr/zmake/tests/test_packers.py index 1709c68098..43b63a908f 100644 --- a/zephyr/zmake/tests/test_packers.py +++ b/zephyr/zmake/tests/test_packers.py @@ -2,9 +2,10 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Tests for zmake packers.""" + import pathlib import tempfile -import unittest.mock as mock import hypothesis import hypothesis.strategies as st @@ -16,42 +17,57 @@ import zmake.output_packers as packers absolute_path = st.from_regex(regex=r"\A/[\w/]*\Z") -@hypothesis.given(absolute_path) +class FakePacker(packers.BasePacker): + """Fake packer to expose protected methods.""" + + def __init__(self, max_size): + super().__init__(project=None) + self.max_size = max_size + + def check_packed_file_size(self, file, dir_map): + """Expose the _check_packed_file_size method.""" + return self._check_packed_file_size(file, dir_map) + + def _get_max_image_bytes(self, dir_map): + return self.max_size + + def pack_firmware(self, work_dir, jobclient, dir_map, version_string=""): + del version_string + assert False + + +@hypothesis.given(st.binary(min_size=101, max_size=200)) @hypothesis.settings(deadline=60000) -def test_file_size_unbounded(path): - packer = packers.BasePacker(project=None) - packer._is_size_bound = mock.Mock(name="_is_size_bound", return_value=False) - file = pathlib.Path(path) / "zephyr.bin" - assert packer._check_packed_file_size(file=file, dirs={}) == file - packer._is_size_bound.assert_called_once_with(file) +def test_file_size_unbounded(data): + """Test with file size unbounded.""" + packer = FakePacker(None) + with tempfile.TemporaryDirectory() as temp_dir_name: + file = pathlib.Path(temp_dir_name) / "zephyr.elf" + with open(file, "wb") as outfile: + outfile.write(data) + assert packer.check_packed_file_size(file=file, dir_map={}) == file @hypothesis.given(st.binary(min_size=5, max_size=100)) @hypothesis.settings(deadline=60000) def test_file_size_in_bounds(data): - packer = packers.BasePacker(project=None) - packer._is_size_bound = mock.Mock(name="_is_size_bound", return_value=True) - packer._get_max_image_bytes = mock.Mock( - name="_get_max_image_bytes", return_value=100 - ) + """Test with file size limited.""" + packer = FakePacker(100) with tempfile.TemporaryDirectory() as temp_dir_name: file = pathlib.Path(temp_dir_name) / "zephyr.bin" - with open(file, "wb") as f: - f.write(data) - assert packer._check_packed_file_size(file=file, dirs={}) == file + with open(file, "wb") as outfile: + outfile.write(data) + assert packer.check_packed_file_size(file=file, dir_map={}) == file @hypothesis.given(st.binary(min_size=101, max_size=200)) @hypothesis.settings(deadline=60000) def test_file_size_out_of_bounds(data): - packer = packers.BasePacker(project=None) - packer._is_size_bound = mock.Mock(name="_is_size_bound", return_value=True) - packer._get_max_image_bytes = mock.Mock( - name="_get_max_image_bytes", return_value=100 - ) + """Test with file size limited, and file exceeds limit.""" + packer = FakePacker(100) with tempfile.TemporaryDirectory() as temp_dir_name: file = pathlib.Path(temp_dir_name) / "zephyr.bin" - with open(file, "wb") as f: - f.write(data) + with open(file, "wb") as outfile: + outfile.write(data) with pytest.raises(RuntimeError): - packer._check_packed_file_size(file=file, dirs={}) + packer.check_packed_file_size(file=file, dir_map={}) diff --git a/zephyr/zmake/tests/test_project.py b/zephyr/zmake/tests/test_project.py index f4808d14d5..b5facbc331 100644 --- a/zephyr/zmake/tests/test_project.py +++ b/zephyr/zmake/tests/test_project.py @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Test zmake project module.""" + import pathlib import string import tempfile @@ -193,6 +195,7 @@ def test_find_projects_name_conflict(tmp_path): def test_register_variant(tmp_path): + """Test registering a variant.""" (tmp_path / "BUILD.py").write_text( """ some = register_raw_project( @@ -236,6 +239,7 @@ another = some_variant.variant( ], ) def test_kconfig_files(tmp_path, actual_files, config_files, expected_files): + """Test for setting kconfig_files property.""" for name in actual_files: (tmp_path / name).write_text("") diff --git a/zephyr/zmake/tests/test_util.py b/zephyr/zmake/tests/test_util.py index 438c5efcf0..1ec0076162 100644 --- a/zephyr/zmake/tests/test_util.py +++ b/zephyr/zmake/tests/test_util.py @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Tests for zmake util.""" + import pathlib import tempfile @@ -19,12 +21,13 @@ version_tuples = st.tuples(version_integers, version_integers, version_integers) @hypothesis.given(version_tuples) @hypothesis.settings(deadline=60000) def test_read_zephyr_version(version_tuple): + """Test reading the zephyr version.""" with tempfile.TemporaryDirectory() as zephyr_base: - with open(pathlib.Path(zephyr_base) / "VERSION", "w") as f: + with open(pathlib.Path(zephyr_base) / "VERSION", "w") as file: for name, value in zip( ("VERSION_MAJOR", "VERSION_MINOR", "PATCHLEVEL"), version_tuple ): - f.write("{} = {}\n".format(name, value)) + file.write("{} = {}\n".format(name, value)) assert util.read_zephyr_version(zephyr_base) == version_tuple @@ -32,10 +35,11 @@ def test_read_zephyr_version(version_tuple): @hypothesis.given(st.integers()) @hypothesis.settings(deadline=60000) def test_read_kconfig_autoconf_value(value): - with tempfile.TemporaryDirectory() as dir: - path = pathlib.Path(dir) - with open(path / "autoconf.h", "w") as f: - f.write("#define TEST {}".format(value)) + """Test reading the kconfig autoconf.""" + with tempfile.TemporaryDirectory() as temp_dir: + path = pathlib.Path(temp_dir) + with open(path / "autoconf.h", "w") as file: + file.write("#define TEST {}".format(value)) read_value = util.read_kconfig_autoconf_value(path, "TEST") assert int(read_value) == value @@ -52,4 +56,5 @@ def test_read_kconfig_autoconf_value(value): ], ) def test_c_str(input_str, expected_result): + """Test the util.c_str function.""" assert util.c_str(input_str) == expected_result diff --git a/zephyr/zmake/tests/test_version.py b/zephyr/zmake/tests/test_version.py index b2c6b43fec..e56e13a519 100644 --- a/zephyr/zmake/tests/test_version.py +++ b/zephyr/zmake/tests/test_version.py @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Tests for zmake version code.""" + import datetime import subprocess import unittest.mock as mock @@ -12,6 +14,8 @@ import zmake.output_packers import zmake.project import zmake.version as version +# pylint:disable=redefined-outer-name,unused-argument + def _git_init(repo): """Create a new git repository.""" @@ -88,6 +92,7 @@ def _setup_example_repos(tmp_path): def test_version_string(tmp_path): + """Test a that version string is as expected.""" project, zephyr_base, modules = _setup_example_repos(tmp_path) assert ( version.get_version_string(project, zephyr_base, modules) @@ -96,6 +101,7 @@ def test_version_string(tmp_path): def test_version_string_static(tmp_path): + """Test a that version string with no git hashes.""" project, zephyr_base, modules = _setup_example_repos(tmp_path) assert ( version.get_version_string(project, zephyr_base, modules, static=True) @@ -105,6 +111,7 @@ def test_version_string_static(tmp_path): @pytest.fixture def fake_user_hostname(): + """Fixture to provide a fake user and hostname.""" with mock.patch("getpass.getuser", return_value="toukmond", autospec=True): with mock.patch("platform.node", return_value="pokey", autospec=True): yield @@ -112,6 +119,7 @@ def fake_user_hostname(): @pytest.fixture def fake_date(): + """Fixture to provide a fake date.""" fixed_date = datetime.datetime(2021, 6, 28, 3, 18, 53) with mock.patch("datetime.datetime") as mock_datetime: mock_datetime.now.return_value = fixed_date @@ -141,6 +149,7 @@ EXPECTED_HEADER_STATIC = ( def test_header_gen(fake_user_hostname, fake_date, tmp_path): + """Test generating the version header.""" # Test the simple case (static=False, no existing header). output_file = tmp_path / "ec_version.h" version.write_version_header(HEADER_VERSION_STR, output_file) @@ -148,6 +157,7 @@ def test_header_gen(fake_user_hostname, fake_date, tmp_path): def test_header_gen_reproducible_build(tmp_path): + """Test that reproducible builds produce the right header.""" # With static=True this time. output_file = tmp_path / "ec_version.h" version.write_version_header(HEADER_VERSION_STR_STATIC, output_file, static=True) @@ -155,6 +165,7 @@ def test_header_gen_reproducible_build(tmp_path): def test_header_gen_exists_not_changed(fake_user_hostname, fake_date, tmp_path): + """Test that the version file is not changed.""" # Test we don't overwrite if no changes needed. output_file = tmp_path / "ec_version.h" @@ -170,6 +181,7 @@ def test_header_gen_exists_not_changed(fake_user_hostname, fake_date, tmp_path): def test_header_gen_exists_needs_changes(fake_user_hostname, fake_date, tmp_path): + """Test that the version file is changed, when needed.""" # Test we overwrite when it exists already and changes are needed. output_file = tmp_path / "ec_version.h" diff --git a/zephyr/zmake/tests/test_zmake.py b/zephyr/zmake/tests/test_zmake.py index ee00330c27..4ca1d7f077 100644 --- a/zephyr/zmake/tests/test_zmake.py +++ b/zephyr/zmake/tests/test_zmake.py @@ -26,7 +26,7 @@ OUR_PATH = os.path.dirname(os.path.realpath(__file__)) class FakeProject: """A fake project which requests two builds and does no packing""" - # pylint: disable=too-few-public-methods,no-self-use + # pylint: disable=too-few-public-methods def __init__(self): self.packer = unittest.mock.Mock() @@ -46,15 +46,18 @@ class FakeProject: yield "ro", zmake.build_config.BuildConfig() yield "rw", zmake.build_config.BuildConfig() - def prune_modules(self, _): + @staticmethod + def prune_modules(_): """Fake implementation of prune_modules.""" return {} # pathlib.Path('path')] - def find_dts_overlays(self, _): + @staticmethod + def find_dts_overlays(_): """Fake implementation of find_dts_overlays.""" return zmake.build_config.BuildConfig() - def get_toolchain(self, module_paths, override=None): + @staticmethod + def get_toolchain(module_paths, override=None): """Fake implementation of get_toolchain.""" return zmake.toolchains.GenericToolchain( override or "foo", @@ -141,7 +144,7 @@ def do_test_with_log_level(zmake_factory_from_dir, log_level, fnames=None): ["fakeproject"], clobber=True, ) - multiproc.wait_for_log_end() + multiproc.LogWriter.wait_for_log_end() recs = [rec.getMessage() for rec in cap.records] return recs @@ -150,14 +153,14 @@ def do_test_with_log_level(zmake_factory_from_dir, log_level, fnames=None): class TestFilters: """Test filtering of stdout and stderr""" - # pylint: disable=no-self-use - - def test_filter_normal(self, zmake_factory_from_dir): + @staticmethod + def test_filter_normal(zmake_factory_from_dir): """Test filtering of a normal build (with no errors)""" recs = do_test_with_log_level(zmake_factory_from_dir, logging.ERROR) assert not recs - def test_filter_info(self, zmake_factory_from_dir, tmp_path): + @staticmethod + def test_filter_info(zmake_factory_from_dir, tmp_path): """Test what appears on the INFO level""" recs = do_test_with_log_level(zmake_factory_from_dir, logging.INFO) # TODO: Remove sets and figure out how to check the lines are in the @@ -180,7 +183,8 @@ class TestFilters: # This produces an easy-to-read diff if there is a difference assert expected == set(recs) - def test_filter_debug(self, zmake_factory_from_dir, tmp_path): + @staticmethod + def test_filter_debug(zmake_factory_from_dir, tmp_path): """Test what appears on the DEBUG level""" recs = do_test_with_log_level(zmake_factory_from_dir, logging.DEBUG) # TODO: Remove sets and figure out how to check the lines are in the @@ -205,7 +209,8 @@ class TestFilters: # This produces an easy-to-read diff if there is a difference assert expected == set(recs) - def test_filter_devicetree_error(self, zmake_factory_from_dir): + @staticmethod + def test_filter_devicetree_error(zmake_factory_from_dir): """Test that devicetree errors appear""" recs = do_test_with_log_level( zmake_factory_from_dir, @@ -278,7 +283,7 @@ def test_list_projects( autospec=True, return_value=fake_projects, ): - zmake_from_dir.list_projects(format=fmt, search_dir=search_dir) + zmake_from_dir.list_projects(fmt=fmt, search_dir=search_dir) captured = capsys.readouterr() assert captured.out == expected_output diff --git a/zephyr/zmake/zmake/__main__.py b/zephyr/zmake/zmake/__main__.py index 9ad509dfc5..fd1dfec13a 100644 --- a/zephyr/zmake/zmake/__main__.py +++ b/zephyr/zmake/zmake/__main__.py @@ -195,6 +195,7 @@ def get_argparser(): list_projects.add_argument( "--format", default="{config.project_name}\n", + dest="fmt", help=( "Output format to print projects (str.format(config=project.config) is " "called on this for each project)." @@ -351,7 +352,7 @@ def main(argv=None): wait_rv = zmake.executor.wait() return result or wait_rv finally: - multiproc.wait_for_log_end() + multiproc.LogWriter.wait_for_log_end() if __name__ == "__main__": diff --git a/zephyr/zmake/zmake/build_config.py b/zephyr/zmake/zmake/build_config.py index ced2c9085c..0d03e22a45 100644 --- a/zephyr/zmake/zmake/build_config.py +++ b/zephyr/zmake/zmake/build_config.py @@ -7,6 +7,7 @@ import hashlib import json import pathlib +import zmake.jobserver import zmake.util as util @@ -18,11 +19,11 @@ class BuildConfig: """ def __init__( - self, environ_defs={}, cmake_defs={}, kconfig_defs={}, kconfig_files=[] + self, environ_defs=None, cmake_defs=None, kconfig_defs=None, kconfig_files=None ): - self.environ_defs = dict(environ_defs) - self.cmake_defs = dict(cmake_defs) - self.kconfig_defs = dict(kconfig_defs) + self.environ_defs = dict(environ_defs or {}) + self.cmake_defs = dict(cmake_defs or {}) + self.kconfig_defs = dict(kconfig_defs or {}) def _remove_duplicate_paths(files): # Remove multiple of the same kconfig file in a row. @@ -32,10 +33,15 @@ class BuildConfig: result.append(path) return result - self.kconfig_files = _remove_duplicate_paths(kconfig_files) + self.kconfig_files = _remove_duplicate_paths(kconfig_files or []) def popen_cmake( - self, jobclient, project_dir, build_dir, kconfig_path=None, **kwargs + self, + jobclient: zmake.jobserver.JobClient, + project_dir, + build_dir, + kconfig_path=None, + **kwargs ): """Run Cmake with this config using a jobclient. diff --git a/zephyr/zmake/zmake/configlib.py b/zephyr/zmake/zmake/configlib.py index a0463f1a86..a5c78ad22d 100644 --- a/zephyr/zmake/zmake/configlib.py +++ b/zephyr/zmake/zmake/configlib.py @@ -15,6 +15,7 @@ def _register_project(**kwargs): def register_host_project(**kwargs): + """Register a project that runs on a posix host.""" kwargs.setdefault("zephyr_board", "native_posix") kwargs.setdefault("supported_toolchains", ["llvm", "host"]) kwargs.setdefault("output_packer", zmake.output_packers.ElfPacker) @@ -22,21 +23,25 @@ def register_host_project(**kwargs): def register_host_test(test_name, **kwargs): + """Register a test project that runs on the host.""" kwargs.setdefault("is_test", True) return register_host_project(project_name="test-{}".format(test_name), **kwargs) def register_raw_project(**kwargs): + """Register a project that uses RawBinPacker.""" kwargs.setdefault("supported_toolchains", ["coreboot-sdk", "zephyr"]) kwargs.setdefault("output_packer", zmake.output_packers.RawBinPacker) return _register_project(**kwargs) def register_binman_project(**kwargs): + """Register a project that uses BinmanPacker.""" kwargs.setdefault("output_packer", zmake.output_packers.BinmanPacker) return register_raw_project(**kwargs) def register_npcx_project(**kwargs): + """Register a project that uses NpcxPacker.""" kwargs.setdefault("output_packer", zmake.output_packers.NpcxPacker) return register_binman_project(**kwargs) diff --git a/zephyr/zmake/zmake/generate_readme.py b/zephyr/zmake/zmake/generate_readme.py index d21fd19f7c..9008f0f45d 100644 --- a/zephyr/zmake/zmake/generate_readme.py +++ b/zephyr/zmake/zmake/generate_readme.py @@ -25,8 +25,8 @@ class MarkdownHelpFormatter(argparse.HelpFormatter): lst = self._section_contents lst.append(text) - def start_section(self, title): - self._section_title = title.title() + def start_section(self, heading): + self._section_title = heading.title() self._section_contents = [] def end_section(self): @@ -35,7 +35,7 @@ class MarkdownHelpFormatter(argparse.HelpFormatter): self._paragraphs.extend(self._section_contents) self._section_title = None - def add_usage(self, usage, actions, groups): + def add_usage(self, usage, actions, groups, prefix=None): if not usage: usage = self._prog self.add_text( @@ -55,8 +55,7 @@ class MarkdownHelpFormatter(argparse.HelpFormatter): else: parts.append(f"{option_string} {_get_metavar(action).upper()}") return ", ".join(f"`{part}`" for part in parts) - else: - return f"`{_get_metavar(action)}`" + return f"`{_get_metavar(action)}`" def _get_table_line(action): return f"| {_format_invocation(action)} | {action.help} |" @@ -89,7 +88,7 @@ def generate_readme(): # Normally, this would not be required, since we don't use from # imports. But runpy's import machinery essentially does the # equivalent of a from import on __main__.py. - import zmake.__main__ + import zmake.__main__ # pylint: disable=import-outside-toplevel output = io.StringIO() parser, sub_action = zmake.__main__.get_argparser() diff --git a/zephyr/zmake/zmake/jobserver.py b/zephyr/zmake/zmake/jobserver.py index 0d02a2c8d6..16f856e607 100644 --- a/zephyr/zmake/zmake/jobserver.py +++ b/zephyr/zmake/zmake/jobserver.py @@ -35,7 +35,8 @@ class JobClient: """Claim a job.""" raise NotImplementedError("Abstract method not implemented") - def env(self): + @staticmethod + def env(): """Get the environment variables necessary to share the job server.""" return {} @@ -54,35 +55,10 @@ class JobClient: logger.debug("Running %s", zmake.util.repr_command(argv)) return subprocess.Popen(argv, **kwargs) - def run(self, *args, claim_job=True, **kwargs): - """Run a process using subprocess.run, optionally claiming a job. - - Args: - claim_job: True if a job should be claimed. - - All other arguments are passed to subprocess.run. - - Returns: - A CompletedProcess object. - """ - if claim_job: - with self.get_job(): - return self.run(*args, claim_job=False, **kwargs) - - kwargs.setdefault("env", os.environ) - kwargs["env"].update(self.env()) - - return subprocess.run(*args, **kwargs) - - -class JobServer(JobClient): - """Abstract Job Server.""" - - def __init__(self, jobs=0): - raise NotImplementedError("Abstract method not implemented") - class GNUMakeJobClient(JobClient): + """A job client for GNU make.""" + def __init__(self, read_fd, write_fd): self._pipe = [read_fd, write_fd] @@ -127,7 +103,7 @@ class GNUMakeJobClient(JobClient): return {"MAKEFLAGS": "--jobserver-auth={},{}".format(*self._pipe)} -class GNUMakeJobServer(JobServer, GNUMakeJobClient): +class GNUMakeJobServer(GNUMakeJobClient): """Implements a GNU Make POSIX Job Server. See https://www.gnu.org/software/make/manual/html_node/POSIX-Jobserver.html @@ -135,10 +111,11 @@ class GNUMakeJobServer(JobServer, GNUMakeJobClient): """ def __init__(self, jobs=0): + [read_fd, write_fd] = os.pipe() + super().__init__(read_fd, write_fd) if not jobs: jobs = multiprocessing.cpu_count() elif jobs > select.PIPE_BUF: jobs = select.PIPE_BUF - self._pipe = os.pipe() os.write(self._pipe[1], b"+" * jobs) diff --git a/zephyr/zmake/zmake/modules.py b/zephyr/zmake/zmake/modules.py index 5ba0ef73f8..91f0dd50b9 100644 --- a/zephyr/zmake/zmake/modules.py +++ b/zephyr/zmake/zmake/modules.py @@ -95,5 +95,4 @@ def setup_module_symlinks(output_dir, modules): return build_config.BuildConfig( cmake_defs={"ZEPHYR_MODULES": ";".join(map(str, module_links))} ) - else: - return build_config.BuildConfig() + return build_config.BuildConfig() diff --git a/zephyr/zmake/zmake/multiproc.py b/zephyr/zmake/zmake/multiproc.py index 94f5f5b69d..7d9a88de5a 100644 --- a/zephyr/zmake/zmake/multiproc.py +++ b/zephyr/zmake/zmake/multiproc.py @@ -1,11 +1,6 @@ # Copyright 2020 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import collections -import logging -import os -import select -import threading """Zmake multiprocessing utility module. @@ -15,22 +10,16 @@ process does not need to finish before the output is available to the developer on the screen. """ -# A local pipe use to signal the look that a new file descriptor was added and -# should be included in the select statement. -_logging_interrupt_pipe = os.pipe() -# A condition variable used to synchronize logging operations. -_logging_cv = threading.Condition() -# A map of file descriptors to their LogWriter -_logging_map = {} -# Should we log job names or not -log_job_names = True - - -def reset(): - """Reset this module to its starting state (useful for tests)""" - global _logging_map +import collections +import io +import logging +import os +import select +import threading +from typing import Any, ClassVar, Dict, List - _logging_map = {} +# Should we log job names or not +LOG_JOB_NAMES = True class LogWriter: @@ -52,7 +41,22 @@ class LogWriter: _file_descriptor: The file descriptor being logged. """ - def __init__( + # A local pipe use to signal the look that a new file descriptor was added and + # should be included in the select statement. + _logging_interrupt_pipe = os.pipe() + # A condition variable used to synchronize logging operations. + _logging_cv = threading.Condition() + # A map of file descriptors to their LogWriter + _logging_map: ClassVar[Dict[io.TextIOBase, "LogWriter"]] = {} + # The thread that handles the reading from pipes and writing to log. + _logging_thread = None + + @classmethod + def reset(cls): + """Reset this module to its starting state (useful for tests)""" + LogWriter._logging_map.clear() + + def __init__( # pylint: disable=too-many-arguments self, logger, log_level, @@ -89,7 +93,7 @@ class LogWriter: # greatly simplifies the logic that is needed to update the log # level. self._log_level = self._override_func(line, self._log_level) - if self._job_id and log_job_names: + if self._job_id and LOG_JOB_NAMES: self._logger.log(self._log_level, "[%s]%s", self._job_id, line) else: self._logger.log(self._log_level, line) @@ -111,141 +115,150 @@ class LogWriter: This method will block execution until all the logs have been flushed out. """ - with _logging_cv: - _logging_cv.wait_for(lambda: self._file_descriptor not in _logging_map) + with LogWriter._logging_cv: + LogWriter._logging_cv.wait_for( + lambda: self._file_descriptor not in LogWriter._logging_map + ) if self._tee_output: self._tee_output.close() self._tee_output = None + @classmethod + def _log_fd(cls, file_descriptor: io.TextIOBase): + """Log information from a single file descriptor. -def _log_fd(fd): - """Log information from a single file descriptor. + This function is BLOCKING. It will read from the given file descriptor until + either the end of line is read or EOF. Once EOF is read it will remove the + file descriptor from _logging_map so it will no longer be used. + Additionally, in some cases, the file descriptor will be closed (caused by + a call to Popen.wait()). In these cases, the file descriptor will also be + removed from the map as it is no longer valid. + """ + with LogWriter._logging_cv: + writer = LogWriter._logging_map[file_descriptor] + if file_descriptor.closed: + del LogWriter._logging_map[file_descriptor] + LogWriter._logging_cv.notify_all() + return + line = file_descriptor.readline() + if not line: + # EOF + del LogWriter._logging_map[file_descriptor] + LogWriter._logging_cv.notify_all() + return + line = line.rstrip("\n") + if line: + writer.log_line(line) + + @classmethod + def _prune_logging_fds(cls): + """Prune the current file descriptors under _logging_map. + + This function will iterate over the logging map and check for closed file + descriptors. Every closed file descriptor will be removed. + """ + with LogWriter._logging_cv: + remove = [ + file_descriptor + for file_descriptor in LogWriter._logging_map + if file_descriptor.closed + ] + for file_descriptor in remove: + del LogWriter._logging_map[file_descriptor] + if remove: + LogWriter._logging_cv.notify_all() + + @classmethod + def _logging_loop(cls): + """The primary logging thread loop. + + This is the entry point of the logging thread. It will listen for (1) any + new data on the output file descriptors that were added via log_output() and + (2) any new file descriptors being added by log_output(). Once a file + descriptor is ready to be read, this function will call _log_fd to perform + the actual read and logging. + """ + while True: + with LogWriter._logging_cv: + LogWriter._logging_cv.wait_for(lambda: LogWriter._logging_map) + keys: List[Any] = list(LogWriter._logging_map.keys()) + keys.append(LogWriter._logging_interrupt_pipe[0]) + try: + fds, _, _ = select.select(keys, [], []) + except ValueError: + # One of the file descriptors must be closed, prune them and try + # again. + LogWriter._prune_logging_fds() + continue + if LogWriter._logging_interrupt_pipe[0] in fds: + # We got a sentinel byte sent by log_output(), this is a signal used to + # break out of the blocking select.select call to tell us that the + # file descriptor set has changed. We just need to read the byte and + # remove this descriptor from the list. If we actually have data + # that should be read it will be read in the for loop below. + os.read(LogWriter._logging_interrupt_pipe[0], 1) + fds.remove(LogWriter._logging_interrupt_pipe[0]) + for file in fds: + LogWriter._log_fd(file) + + @classmethod + def log_output( # pylint: disable=too-many-arguments + cls, + logger, + log_level, + file_descriptor, + log_level_override_func=None, + job_id=None, + tee_output=None, + ): + """Log the output from the given file descriptor. - This function is BLOCKING. It will read from the given file descriptor until - either the end of line is read or EOF. Once EOF is read it will remove the - file descriptor from _logging_map so it will no longer be used. - Additionally, in some cases, the file descriptor will be closed (caused by - a call to Popen.wait()). In these cases, the file descriptor will also be - removed from the map as it is no longer valid. - """ - with _logging_cv: - writer = _logging_map[fd] - if fd.closed: - del _logging_map[fd] - _logging_cv.notify_all() - return - line = fd.readline() - if not line: - # EOF - del _logging_map[fd] - _logging_cv.notify_all() - return - line = line.rstrip("\n") - if line: - writer.log_line(line) - - -def _prune_logging_fds(): - """Prune the current file descriptors under _logging_map. - - This function will iterate over the logging map and check for closed file - descriptors. Every closed file descriptor will be removed. - """ - with _logging_cv: - remove = [fd for fd in _logging_map.keys() if fd.closed] - for fd in remove: - del _logging_map[fd] - if remove: - _logging_cv.notify_all() - - -def _logging_loop(): - """The primary logging thread loop. - - This is the entry point of the logging thread. It will listen for (1) any - new data on the output file descriptors that were added via log_output() and - (2) any new file descriptors being added by log_output(). Once a file - descriptor is ready to be read, this function will call _log_fd to perform - the actual read and logging. - """ - while True: - with _logging_cv: - _logging_cv.wait_for(lambda: _logging_map) - keys = list(_logging_map.keys()) + [_logging_interrupt_pipe[0]] - try: - fds, _, _ = select.select(keys, [], []) - except ValueError: - # One of the file descriptors must be closed, prune them and try - # again. - _prune_logging_fds() - continue - if _logging_interrupt_pipe[0] in fds: - # We got a dummy byte sent by log_output(), this is a signal used to - # break out of the blocking select.select call to tell us that the - # file descriptor set has changed. We just need to read the byte and - # remove this descriptor from the list. If we actually have data - # that should be read it will be read in the for loop below. - os.read(_logging_interrupt_pipe[0], 1) - fds.remove(_logging_interrupt_pipe[0]) - for fd in fds: - _log_fd(fd) - - -_logging_thread = None - - -def log_output( - logger, - log_level, - file_descriptor, - log_level_override_func=None, - job_id=None, - tee_output=None, -): - """Log the output from the given file descriptor. - - Args: - logger: The logger object to use. - log_level: The logging level to use. - file_descriptor: The file descriptor to read from. - log_level_override_func: A function used to override the log level. The - function will be called once per line prior to logging and will be - passed the arguments of the line and the default log level. - - Returns: - LogWriter object for the resulting output - """ - with _logging_cv: - global _logging_thread - if _logging_thread is None or not _logging_thread.is_alive(): - # First pass or thread must have died, create a new one. - _logging_thread = threading.Thread(target=_logging_loop, daemon=True) - _logging_thread.start() - - writer = LogWriter( - logger, - log_level, - log_level_override_func, - job_id, - file_descriptor, - tee_output=tee_output, - ) - _logging_map[file_descriptor] = writer - # Write a dummy byte to the pipe to break the select so we can add the - # new fd. - os.write(_logging_interrupt_pipe[1], b"x") - # Notify the condition so we can run the select on the current fds. - _logging_cv.notify_all() - return writer - - -def wait_for_log_end(): - """Wait for all the logs to be printed. - - This method will block execution until all the logs have been flushed out. - """ - with _logging_cv: - _logging_cv.wait_for(lambda: not _logging_map) + Args: + logger: The logger object to use. + log_level: The logging level to use. + file_descriptor: The file descriptor to read from. + log_level_override_func: A function used to override the log level. The + function will be called once per line prior to logging and will be + passed the arguments of the line and the default log level. + + Returns: + LogWriter object for the resulting output + """ + with LogWriter._logging_cv: + if ( + LogWriter._logging_thread is None + or not LogWriter._logging_thread.is_alive() + ): + # First pass or thread must have died, create a new one. + LogWriter._logging_thread = threading.Thread( + target=LogWriter._logging_loop, daemon=True + ) + LogWriter._logging_thread.start() + + writer = LogWriter( + logger, + log_level, + log_level_override_func, + job_id, + file_descriptor, + tee_output=tee_output, + ) + LogWriter._logging_map[file_descriptor] = writer + # Write a sentinel byte to the pipe to break the select so we can add the + # new fd. + os.write(LogWriter._logging_interrupt_pipe[1], b"x") + # Notify the condition so we can run the select on the current fds. + LogWriter._logging_cv.notify_all() + return writer + + @classmethod + def wait_for_log_end(cls): + """Wait for all the logs to be printed. + + This method will block execution until all the logs have been flushed out. + """ + with LogWriter._logging_cv: + LogWriter._logging_cv.wait_for(lambda: not LogWriter._logging_map) class Executor: @@ -315,8 +328,8 @@ class Executor: """ try: result = func() - except Exception as ex: - self.logger.exception(ex) + except Exception as e: # pylint: disable=broad-except + self.logger.exception(e) result = -1 with self.lock: self.results.append(result) diff --git a/zephyr/zmake/zmake/output_packers.py b/zephyr/zmake/zmake/output_packers.py index eae7358157..24a72425d6 100644 --- a/zephyr/zmake/zmake/output_packers.py +++ b/zephyr/zmake/zmake/output_packers.py @@ -5,8 +5,11 @@ import logging import shutil import subprocess +from pathlib import Path +from typing import Dict, Optional import zmake.build_config as build_config +import zmake.jobserver import zmake.multiproc import zmake.util as util @@ -17,7 +20,8 @@ class BasePacker: def __init__(self, project): self.project = project - def configs(self): + @staticmethod + def configs(): """Get all of the build configurations necessary. Yields: @@ -25,7 +29,13 @@ class BasePacker: """ yield "singleimage", build_config.BuildConfig() - def pack_firmware(self, work_dir, jobclient, version_string=""): + def pack_firmware( + self, + work_dir, + jobclient: zmake.jobserver.JobClient, + dir_map: Dict[str, Path], + version_string="", + ): """Pack a firmware image. Config names from the configs generator are passed as keyword @@ -36,6 +46,7 @@ class BasePacker: work_dir: A directory to write outputs and temporary files into. jobclient: A JobClient object to use. + dir_map: A dict of build dirs such as {'ro': path_to_ro_dir}. version_string: The version string, which may end up in certain parts of the outputs. @@ -46,44 +57,38 @@ class BasePacker: """ raise NotImplementedError("Abstract method not implemented") - def _get_max_image_bytes(self): + @staticmethod + def _get_max_image_bytes(dir_map) -> Optional[int]: """Get the maximum allowed image size (in bytes). This value will generally be found in CONFIG_FLASH_SIZE but may vary depending on the specific way things are being packed. - Returns: - The maximum allowed size of the image in bytes. - """ - raise NotImplementedError("Abstract method not implemented") - - def _is_size_bound(self, path): - """Check whether the given path should be constrained by size. - - Generally, .elf files will be unconstrained while .bin files will be - constrained. - Args: - path: A file's path to test. + file: A file to test. + dir_map: A dict of build dirs such as {'ro': path_to_ro_dir}. Returns: - True if the file size should be checked. False otherwise. + The maximum allowed size of the image in bytes, or None if the size + is not limited. """ - return path.suffix == ".bin" + del dir_map - def _check_packed_file_size(self, file, dirs): + def _check_packed_file_size(self, file, dir_map): """Check that a packed file passes size constraints. Args: file: A file to test. - dirs: A map of the arguments to pass to _get_max_image_bytes + dir_map: A dict of build dirs such as {'ro': path_to_ro_dir}. + Returns: The file if it passes the test. """ - if not self._is_size_bound( - file - ) or file.stat().st_size <= self._get_max_image_bytes(**dirs): + max_size = self._get_max_image_bytes( # pylint: disable=assignment-from-none + dir_map + ) + if max_size is None or file.stat().st_size <= max_size: return file raise RuntimeError("Output file ({}) too large".format(file)) @@ -91,15 +96,17 @@ class BasePacker: class ElfPacker(BasePacker): """Raw proxy for ELF output of a single build.""" - def pack_firmware(self, work_dir, jobclient, singleimage, version_string=""): - yield singleimage / "zephyr" / "zephyr.elf", "zephyr.elf" + def pack_firmware(self, work_dir, jobclient, dir_map, version_string=""): + del version_string + yield dir_map["singleimage"] / "zephyr" / "zephyr.elf", "zephyr.elf" class RawBinPacker(BasePacker): """Raw proxy for zephyr.bin output of a single build.""" - def pack_firmware(self, work_dir, jobclient, singleimage, version_string=""): - yield singleimage / "zephyr" / "zephyr.bin", "zephyr.bin" + def pack_firmware(self, work_dir, jobclient, dir_map, version_string=""): + del version_string + yield dir_map["singleimage"] / "zephyr" / "zephyr.bin", "zephyr.bin" class BinmanPacker(BasePacker): @@ -116,7 +123,9 @@ class BinmanPacker(BasePacker): yield "ro", build_config.BuildConfig(kconfig_defs={"CONFIG_CROS_EC_RO": "y"}) yield "rw", build_config.BuildConfig(kconfig_defs={"CONFIG_CROS_EC_RW": "y"}) - def pack_firmware(self, work_dir, jobclient, ro, rw, version_string=""): + def pack_firmware( + self, work_dir, jobclient: zmake.jobserver.JobClient, dir_map, version_string="" + ): """Pack RO and RW sections using Binman. Binman configuration is expected to be found in the RO build @@ -125,8 +134,7 @@ class BinmanPacker(BasePacker): Args: work_dir: The directory used for packing. jobclient: The client used to run subprocesses. - ro: Directory containing the RO image build. - rw: Directory containing the RW image build. + dir_map: A dict of build dirs such as {'ro': path_to_ro_dir}. version_string: The version string to use in FRID/FWID. Yields: @@ -134,12 +142,14 @@ class BinmanPacker(BasePacker): should be copied into the output directory, and the output filename. """ - dts_file_path = ro / "zephyr" / "zephyr.dts" + ro_dir = dir_map["ro"] + rw_dir = dir_map["rw"] + dts_file_path = ro_dir / "zephyr" / "zephyr.dts" # Copy the inputs into the work directory so that Binman can # find them under a hard-coded name. - shutil.copy2(ro / "zephyr" / self.ro_file, work_dir / "zephyr_ro.bin") - shutil.copy2(rw / "zephyr" / self.rw_file, work_dir / "zephyr_rw.bin") + shutil.copy2(ro_dir / "zephyr" / self.ro_file, work_dir / "zephyr_ro.bin") + shutil.copy2(rw_dir / "zephyr" / self.rw_file, work_dir / "zephyr_rw.bin") # Version in FRID/FWID can be at most 31 bytes long (32, minus # one for null character). @@ -166,14 +176,14 @@ class BinmanPacker(BasePacker): encoding="utf-8", ) - zmake.multiproc.log_output(self.logger, logging.DEBUG, proc.stdout) - zmake.multiproc.log_output(self.logger, logging.ERROR, proc.stderr) + zmake.multiproc.LogWriter.log_output(self.logger, logging.DEBUG, proc.stdout) + zmake.multiproc.LogWriter.log_output(self.logger, logging.ERROR, proc.stderr) if proc.wait(timeout=60): raise OSError("Failed to run binman") yield work_dir / "zephyr.bin", "zephyr.bin" - yield ro / "zephyr" / "zephyr.elf", "zephyr.ro.elf" - yield rw / "zephyr" / "zephyr.elf", "zephyr.rw.elf" + yield ro_dir / "zephyr" / "zephyr.elf", "zephyr.ro.elf" + yield rw_dir / "zephyr" / "zephyr.elf", "zephyr.rw.elf" class NpcxPacker(BinmanPacker): @@ -187,37 +197,39 @@ class NpcxPacker(BinmanPacker): ro_file = "zephyr.npcx.bin" npcx_monitor = "npcx_monitor.bin" - def _get_max_image_bytes(self, ro, rw): + def _get_max_image_bytes(self, dir_map): + ro_dir = dir_map["ro"] + rw_dir = dir_map["rw"] ro_size = util.read_kconfig_autoconf_value( - ro / "zephyr" / "include" / "generated", + ro_dir / "zephyr" / "include" / "generated", "CONFIG_PLATFORM_EC_FLASH_SIZE_BYTES", ) rw_size = util.read_kconfig_autoconf_value( - ro / "zephyr" / "include" / "generated", + rw_dir / "zephyr" / "include" / "generated", "CONFIG_PLATFORM_EC_FLASH_SIZE_BYTES", ) return max(int(ro_size, 0), int(rw_size, 0)) # This can probably be removed too and just rely on binman to # check the sizes... see the comment above. - def pack_firmware(self, work_dir, jobclient, ro, rw, version_string=""): + def pack_firmware(self, work_dir, jobclient, dir_map, version_string=""): + ro_dir = dir_map["ro"] for path, output_file in super().pack_firmware( work_dir, jobclient, - ro, - rw, + dir_map, version_string=version_string, ): if output_file == "zephyr.bin": yield ( - self._check_packed_file_size(path, {"ro": ro, "rw": rw}), + self._check_packed_file_size(path, dir_map), "zephyr.bin", ) else: yield path, output_file # Include the NPCX monitor file as an output artifact. - yield ro / self.npcx_monitor, self.npcx_monitor + yield ro_dir / self.npcx_monitor, self.npcx_monitor # A dictionary mapping packer config names to classes. diff --git a/zephyr/zmake/zmake/project.py b/zephyr/zmake/zmake/project.py index b2232bb263..f52caa921d 100644 --- a/zephyr/zmake/zmake/project.py +++ b/zephyr/zmake/zmake/project.py @@ -6,11 +6,12 @@ import dataclasses import logging import pathlib -from typing import Callable, Dict, List +import typing import zmake.build_config as build_config import zmake.configlib as configlib import zmake.modules +import zmake.output_packers import zmake.toolchains as toolchains @@ -29,11 +30,14 @@ def module_dts_overlay_name(modpath, board_name): @dataclasses.dataclass class ProjectConfig: + """All the information needed to define a project.""" + + # pylint: disable=too-many-instance-attributes project_name: str zephyr_board: str supported_toolchains: "list[str]" output_packer: type - modules: "list[str]" = dataclasses.field( + modules: "dict[str, typing.Any]" = dataclasses.field( default_factory=lambda: zmake.modules.known_modules, ) is_test: bool = dataclasses.field(default=False) @@ -48,7 +52,7 @@ class Project: def __init__(self, config: ProjectConfig): self.config = config - self.packer = self.config.output_packer(self) + self.packer: zmake.output_packers.BasePacker = self.config.output_packer(self) def iter_builds(self): """Iterate thru the build combinations provided by the project's packer. @@ -94,8 +98,7 @@ class Project: return build_config.BuildConfig( cmake_defs={"DTC_OVERLAY_FILE": ";".join(map(str, overlays))} ) - else: - return build_config.BuildConfig() + return build_config.BuildConfig() def prune_modules(self, module_paths): """Reduce a modules dict to the ones required by this project. @@ -129,6 +132,7 @@ class Project: return result def get_toolchain(self, module_paths, override=None): + """Get the first supported toolchain that is actually available.""" if override: if override not in self.config.supported_toolchains: logging.warning( @@ -139,19 +143,18 @@ class Project: override, toolchains.GenericToolchain ) return support_class(name=override, modules=module_paths) - else: - for name in self.config.supported_toolchains: - support_class = toolchains.support_classes[name] - toolchain = support_class(name=name, modules=module_paths) - if toolchain.probe(): - logging.info("Toolchain %r selected by probe function.", toolchain) - return toolchain - raise OSError( - "No supported toolchains could be found on your system. If you see " - "this message in the chroot, it indicates a bug. Otherwise, you'll " - "either want to setup your system with a supported toolchain, or " - "manually select an unsupported toolchain with the -t flag." - ) + for name in self.config.supported_toolchains: + support_class = toolchains.support_classes[name] + toolchain = support_class(name=name, modules=module_paths) + if toolchain.probe(): + logging.info("Toolchain %r selected by probe function.", toolchain) + return toolchain + raise OSError( + "No supported toolchains could be found on your system. If you see " + "this message in the chroot, it indicates a bug. Otherwise, you'll " + "either want to setup your system with a supported toolchain, or " + "manually select an unsupported toolchain with the -t flag." + ) @dataclasses.dataclass @@ -167,7 +170,7 @@ class ProjectRegistrationHandler: """ base_config: ProjectConfig - register_func: Callable[[], "ProjectRegistrationHandler"] + register_func: typing.Callable[[], "ProjectRegistrationHandler"] def variant(self, **kwargs) -> "ProjectRegistrationHandler": """Register a new variant based on the base config. @@ -189,7 +192,7 @@ class ProjectRegistrationHandler: return self.register_func(**new_config) -def load_config_file(path) -> List[Project]: +def load_config_file(path) -> typing.List[Project]: """Load a BUILD.py config file and create associated projects. Args: @@ -198,7 +201,7 @@ def load_config_file(path) -> List[Project]: Returns: A list of Project objects specified by the file. """ - projects: List[Project] = [] + projects: typing.List[Project] = [] def register_project(**kwargs) -> ProjectRegistrationHandler: config = ProjectConfig(**kwargs) @@ -220,17 +223,17 @@ def load_config_file(path) -> List[Project]: configlib.__file__, "exec", ) - exec(code, config_globals) + exec(code, config_globals) # pylint: disable=exec-used # Next, load the BUILD.py logging.debug("Loading config file %s", path) code = compile(path.read_bytes(), str(path), "exec") - exec(code, config_globals) + exec(code, config_globals) # pylint: disable=exec-used logging.debug("Config file %s defines %s projects", path, len(projects)) return projects -def find_projects(root_dir) -> Dict[str, Project]: +def find_projects(root_dir) -> typing.Dict[str, Project]: """Finds all zmake projects in root_dir. Args: diff --git a/zephyr/zmake/zmake/toolchains.py b/zephyr/zmake/zmake/toolchains.py index 13ee30de08..8ed1112e25 100644 --- a/zephyr/zmake/zmake/toolchains.py +++ b/zephyr/zmake/zmake/toolchains.py @@ -20,7 +20,8 @@ class GenericToolchain: self.name = name self.modules = modules or {} - def probe(self): # pylint:disable=no-self-use + @staticmethod + def probe(): """Probe if the toolchain is available on the system.""" # Since the toolchain is not known to zmake, we have no way to # know if it's installed. Simply return False to indicate not diff --git a/zephyr/zmake/zmake/util.py b/zephyr/zmake/zmake/util.py index ee3b245b78..22d45d7deb 100644 --- a/zephyr/zmake/zmake/util.py +++ b/zephyr/zmake/zmake/util.py @@ -74,8 +74,8 @@ def read_kconfig_file(path): A dictionary of kconfig items to their values. """ result = {} - with open(path) as f: - for line in f: + with open(path) as file: + for line in file: line, _, _ = line.partition("#") line = line.strip() if line: @@ -95,11 +95,12 @@ def read_kconfig_autoconf_value(path, key): The value associated with the key or nothing if the key wasn't found. """ prog = re.compile(r"^#define\s{}\s(\S+)$".format(key)) - with open(path / "autoconf.h") as f: - for line in f: - m = prog.match(line) - if m: - return m.group(1) + with open(path / "autoconf.h") as file: + for line in file: + match = prog.match(line) + if match: + return match.group(1) + return None def write_kconfig_file(path, config, only_if_changed=True): @@ -114,9 +115,9 @@ def write_kconfig_file(path, config, only_if_changed=True): if only_if_changed: if path.exists() and read_kconfig_file(path) == config: return - with open(path, "w") as f: + with open(path, "w") as file: for name, value in config.items(): - f.write("{}={}\n".format(name, value)) + file.write("{}={}\n".format(name, value)) def read_zephyr_version(zephyr_base): @@ -131,9 +132,9 @@ def read_zephyr_version(zephyr_base): version_file = pathlib.Path(zephyr_base) / "VERSION" file_vars = {} - with open(version_file) as f: - for line in f: - key, sep, value = line.partition("=") + with open(version_file) as file: + for line in file: + key, _, value = line.partition("=") file_vars[key.strip()] = value.strip() return ( diff --git a/zephyr/zmake/zmake/version.py b/zephyr/zmake/zmake/version.py index b2b897cf5b..2333ad46df 100644 --- a/zephyr/zmake/zmake/version.py +++ b/zephyr/zmake/zmake/version.py @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +"""Code to generate the ec_version.h file.""" + import datetime import getpass import io diff --git a/zephyr/zmake/zmake/zmake.py b/zephyr/zmake/zmake/zmake.py index 9b9a709aa9..53dd6575c8 100644 --- a/zephyr/zmake/zmake/zmake.py +++ b/zephyr/zmake/zmake/zmake.py @@ -11,7 +11,7 @@ import pathlib import re import shutil import subprocess -from typing import Dict, List +from typing import Dict, List, Optional, Union import zmake.build_config import zmake.generate_readme @@ -37,6 +37,7 @@ def ninja_stdout_log_level_override(line, current_log_level): current_log_level: The active logging level that would be used for the line. """ + # pylint: disable=too-many-return-statements # Output lines from Zephyr that are not normally useful # Send any lines that start with these strings to INFO cmake_suppress = [ @@ -105,7 +106,7 @@ def cmake_log_level_override(line, default_log_level): # Strange output from Zephyr that we normally ignore if line.startswith("Including boilerplate"): return logging.DEBUG - elif line.startswith("devicetree error:"): + if line.startswith("devicetree error:"): return logging.ERROR if ninja_warnings.match(line): return logging.WARNING @@ -149,17 +150,19 @@ class Zmake: before launching more, False to just do this after all jobs complete """ - def __init__( + # pylint: disable=too-many-instance-attributes + + def __init__( # pylint: disable=too-many-arguments self, checkout=None, - jobserver=None, + jobserver: Optional[zmake.jobserver.JobClient] = None, jobs=0, goma=False, gomacc="/mnt/host/depot_tools/.cipd_bin/gomacc", modules_dir=None, zephyr_base=None, ): - zmake.multiproc.reset() + zmake.multiproc.LogWriter.reset() self.logger = logging.getLogger(self.__class__.__name__) self._checkout = checkout self.goma = goma @@ -187,6 +190,7 @@ class Zmake: @property def checkout(self): + """Returns the location of the cros checkout.""" if not self._checkout: self._checkout = util.locate_cros_checkout() return self._checkout.resolve() @@ -200,7 +204,7 @@ class Zmake: """ found_projects = zmake.project.find_projects(self.module_paths["ec"] / "zephyr") if all_projects: - projects = found_projects.values() + projects = list(found_projects.values()) elif host_tests_only: projects = [p for p in found_projects.values() if p.config.is_test] else: @@ -212,7 +216,7 @@ class Zmake: raise KeyError("No project named {}".format(project_name)) from e return projects - def configure( + def configure( # pylint: disable=too-many-arguments,too-many-locals self, project_names, build_dir=None, @@ -253,33 +257,33 @@ class Zmake: ) ) if self._sequential: - rv = self.executor.wait() - if rv: - return rv - rv = self.executor.wait() - if rv: - return rv + result = self.executor.wait() + if result: + return result + result = self.executor.wait() + if result: + return result test_projects = [p for p in projects if p.config.is_test] if len(test_projects) > 1 and coverage and test_after_configure: - rv = self._merge_lcov_files( + result = self._merge_lcov_files( projects=test_projects, build_dir=build_dir, output_file=build_dir / "all_tests.info", ) - if rv: - return rv + if result: + return result non_test_projects = [p for p in projects if not p.config.is_test] if len(non_test_projects) > 1 and coverage and build_after_configure: - rv = self._merge_lcov_files( + result = self._merge_lcov_files( projects=non_test_projects, build_dir=build_dir, output_file=build_dir / "all_builds.info", ) - if rv: - return rv + if result: + return result return 0 - def build( + def build( # pylint: disable=too-many-arguments self, project_names, build_dir=None, @@ -307,7 +311,7 @@ class Zmake: build_after_configure=True, ) - def test( + def test( # pylint: disable=too-many-arguments,too-many-locals self, project_names, build_dir=None, @@ -362,23 +366,23 @@ class Zmake: ) ) if self._sequential: - rv = self.executor.wait() - if rv: - return rv - rv = self.executor.wait() - if rv: - return rv + result = self.executor.wait() + if result: + return result + result = self.executor.wait() + if result: + return result if len(test_projects) > 1 and coverage: - rv = self._merge_lcov_files( + result = self._merge_lcov_files( projects=test_projects, build_dir=build_dir, output_file=build_dir / "all_tests.info", ) - if rv: - return rv + if result: + return result return 0 - def testall( + def testall( # pylint: disable=too-many-arguments self, build_dir=None, toolchain=None, @@ -387,6 +391,7 @@ class Zmake: coverage=False, allow_warnings=False, ): + """Locate and build all the projects.""" return self.test( [], build_dir=build_dir, @@ -411,6 +416,8 @@ class Zmake: allow_warnings=False, extra_cflags=None, ): + # pylint: disable=too-many-arguments,too-many-locals,too-many-branches + # pylint: disable=too-many-statements """Set up a build directory to later be built by "zmake build".""" # Resolve build_dir if needed. if not build_dir: @@ -487,7 +494,7 @@ class Zmake: files_to_write = [] self.logger.info("Building %s in %s.", project.config.project_name, build_dir) for build_name, build_config in project.iter_builds(): - config = ( + config: zmake.build_config.BuildConfig = ( base_config | toolchain_config | module_config @@ -507,8 +514,7 @@ class Zmake: build_name, ) continue - else: - config_json_file.unlink() + config_json_file.unlink() files_to_write.append((config_json_file, config_json)) @@ -534,14 +540,14 @@ class Zmake: errors="replace", ) job_id = "{}:{}".format(project.config.project_name, build_name) - zmake.multiproc.log_output( + zmake.multiproc.LogWriter.log_output( self.logger, logging.DEBUG, proc.stdout, log_level_override_func=cmake_log_level_override, job_id=job_id, ) - zmake.multiproc.log_output( + zmake.multiproc.LogWriter.log_output( self.logger, logging.ERROR, proc.stderr, @@ -567,14 +573,14 @@ class Zmake: output_files = [] if build_after_configure or test_after_configure: - rv = self._build( + result = self._build( build_dir=build_dir, project=project, coverage=coverage, output_files_out=output_files, ) - if rv: - return rv + if result: + return result if test_after_configure and project.config.is_test: gcov = "gcov.sh-not-found" for build_name, _ in project.iter_builds(): @@ -601,6 +607,7 @@ class Zmake: output_files_out=None, coverage=False, ): + # pylint: disable=too-many-locals,too-many-branches """Build a pre-configured build directory.""" def wait_and_check_success(procs, writers): @@ -668,7 +675,7 @@ class Zmake: "Building %s:%s: %s", project.config.project_name, build_name, - zmake.util.repr_command(cmd), + util.repr_command(cmd), ) proc = self.jobserver.popen( cmd, @@ -680,7 +687,7 @@ class Zmake: job_id = "{}:{}".format(project.config.project_name, build_name) dirs[build_name].mkdir(parents=True, exist_ok=True) build_log = open(dirs[build_name] / "build.log", "w") - out = zmake.multiproc.log_output( + out = zmake.multiproc.LogWriter.log_output( logger=self.logger, log_level=logging.INFO, file_descriptor=proc.stdout, @@ -688,7 +695,7 @@ class Zmake: job_id=job_id, tee_output=build_log, ) - err = zmake.multiproc.log_output( + err = zmake.multiproc.LogWriter.log_output( self.logger, logging.ERROR, proc.stderr, @@ -708,9 +715,9 @@ class Zmake: # Run the packer. packer_work_dir = build_dir / "packer" output_dir = build_dir / "output" - for d in output_dir, packer_work_dir: - if not d.exists(): - d.mkdir() + for newdir in output_dir, packer_work_dir: + if not newdir.exists(): + newdir.mkdir() if output_files_out is None: output_files_out = [] @@ -723,7 +730,7 @@ class Zmake: ) else: for output_file, output_name in project.packer.pack_firmware( - packer_work_dir, self.jobserver, version_string=version_string, **dirs + packer_work_dir, self.jobserver, dirs, version_string=version_string ): shutil.copy2(output_file, output_dir / output_name) self.logger.debug("Output file '%s' created.", output_file) @@ -731,7 +738,7 @@ class Zmake: return 0 - def _run_test( + def _run_test( # pylint: disable=too-many-arguments self, elf_file: pathlib.Path, coverage, gcov, build_dir, lcov_file, timeout=None ): """Run a single test, with goma if enabled. @@ -760,13 +767,13 @@ class Zmake: errors="replace", ) job_id = "test {}".format(elf_file) - zmake.multiproc.log_output( + zmake.multiproc.LogWriter.log_output( self.logger, logging.DEBUG, proc.stdout, job_id=job_id, ) - zmake.multiproc.log_output( + zmake.multiproc.LogWriter.log_output( self.logger, logging.ERROR, proc.stderr, @@ -791,7 +798,9 @@ class Zmake: with self.jobserver.get_job(): _run() - def _run_lcov(self, build_dir, lcov_file, initial=False, gcov=""): + def _run_lcov( + self, build_dir, lcov_file, initial=False, gcov: Union[os.PathLike, str] = "" + ): gcov = os.path.abspath(gcov) if initial: self.logger.info("Running (initial) lcov on %s.", build_dir) @@ -821,7 +830,7 @@ class Zmake: encoding="utf-8", errors="replace", ) - zmake.multiproc.log_output( + zmake.multiproc.LogWriter.log_output( self.logger, logging.WARNING, proc.stderr, @@ -864,21 +873,21 @@ class Zmake: encoding="utf-8", errors="replace", ) - zmake.multiproc.log_output( + zmake.multiproc.LogWriter.log_output( self.logger, logging.ERROR, proc.stderr, job_id="lcov" ) - zmake.multiproc.log_output( + zmake.multiproc.LogWriter.log_output( self.logger, logging.DEBUG, proc.stdout, job_id="lcov" ) if proc.wait(): raise OSError(get_process_failure_msg(proc)) return 0 - def list_projects(self, format, search_dir): + def list_projects(self, fmt, search_dir): """List project names known to zmake on stdout. Args: - format: The formatting string to print projects with. + fmt: The formatting string to print projects with. search_dir: Directory to start the search for BUILD.py files at. """ @@ -886,7 +895,7 @@ class Zmake: search_dir = self.module_paths["ec"] / "zephyr" for project in zmake.project.find_projects(search_dir).values(): - print(format.format(config=project.config), end="") + print(fmt.format(config=project.config), end="") return 0 |