From 8aec32f6abd722b141d96bc095999efa76bd0327 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 16 Jan 2021 14:52:26 -0700 Subject: [PATCH] cros_ec: Support reading EC features The EC can support a variety of features and provides a way to find out what is available. Add support for this. Also update the feature list to the lastest available while we are here. This is at: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/include/ec_commands.h Signed-off-by: Simon Glass --- cmd/cros_ec.c | 74 ++++++++++++++++++++++++++++++++++ drivers/misc/cros_ec.c | 26 +++++++++--- drivers/misc/cros_ec_sandbox.c | 11 +++++ include/cros_ec.h | 21 ++++++++++ include/ec_commands.h | 45 +++++++++++++++++++-- test/dm/cros_ec.c | 28 +++++++++++++ 6 files changed, 195 insertions(+), 10 deletions(-) diff --git a/cmd/cros_ec.c b/cmd/cros_ec.c index 4e85e184fe..77656a2308 100644 --- a/cmd/cros_ec.c +++ b/cmd/cros_ec.c @@ -94,6 +94,74 @@ static int do_read_write(struct udevice *dev, int is_write, int argc, return 0; } +static const char *const feat_name[64] = { + "limited", + "flash", + "pwm_fan", + "pwm_keyb", + "lightbar", + "led", + "motion_sense", + "keyb", + "pstore", + "port80", + "thermal", + "bklight_switch", + "wifi_switch", + "host_events", + "gpio", + "i2c", + "charger", + "battery", + "smart_battery", + "hang_detect", + "pmu", + "sub_mcu", + "usb_pd", + "usb_mux", + "motion_sense_fifo", + "vstore", + "usbc_ss_mux_virtual", + "rtc", + "fingerprint", + "touchpad", + "rwsig", + "device_event", + "unified_wake_masks", + "host_event64", + "exec_in_ram", + "cec", + "motion_sense_tight_timestamps", + "refined_tablet_mode_hysteresis", + "efs2", + "scp", + "ish", + "typec_cmd", + "typec_require_ap_mode_entry", + "typec_mux_require_ap_ack", +}; + +static int do_show_features(struct udevice *dev) +{ + u64 feat; + int ret; + uint i; + + ret = cros_ec_get_features(dev, &feat); + if (ret) + return ret; + for (i = 0; i < ARRAY_SIZE(feat_name); i++) { + if (feat & (1ULL << i)) { + if (feat_name[i]) + printf("%s\n", feat_name[i]); + else + printf("unknown %d\n", i); + } + } + + return 0; +} + static int do_cros_ec(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { @@ -140,6 +208,11 @@ static int do_cros_ec(struct cmd_tbl *cmdtp, int flag, int argc, } printf("rows = %u\n", info.rows); printf("cols = %u\n", info.cols); + } else if (!strcmp("features", cmd)) { + ret = do_show_features(dev); + + if (ret) + printf("Error: %d\n", ret); } else if (0 == strcmp("curimage", cmd)) { enum ec_current_image image; @@ -379,6 +452,7 @@ U_BOOT_CMD( "init Re-init CROS-EC (done on startup automatically)\n" "crosec id Read CROS-EC ID\n" "crosec info Read CROS-EC info\n" + "crosec features Read CROS-EC features\n" "crosec curimage Read CROS-EC current image\n" "crosec hash Read CROS-EC hash\n" "crosec reboot [rw | ro | cold] Reboot CROS-EC\n" diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index 80709be2f1..fd2f2abd7e 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -1344,19 +1344,33 @@ int cros_ec_i2c_tunnel(struct udevice *dev, int port, struct i2c_msg *in, return 0; } -int cros_ec_check_feature(struct udevice *dev, int feature) +int cros_ec_get_features(struct udevice *dev, u64 *featuresp) { struct ec_response_get_features r; int rv; - rv = ec_command(dev, EC_CMD_GET_FEATURES, 0, &r, sizeof(r), NULL, 0); - if (rv) - return rv; + rv = ec_command(dev, EC_CMD_GET_FEATURES, 0, NULL, 0, &r, sizeof(r)); + if (rv != sizeof(r)) + return -EIO; + *featuresp = r.flags[0] | (u64)r.flags[1] << 32; + + return 0; +} + +int cros_ec_check_feature(struct udevice *dev, uint feature) +{ + struct ec_response_get_features r; + int rv; + + rv = ec_command(dev, EC_CMD_GET_FEATURES, 0, NULL, 0, &r, sizeof(r)); + if (rv != sizeof(r)) + return -EIO; if (feature >= 8 * sizeof(r.flags)) - return -1; + return -EINVAL; - return r.flags[feature / 32] & EC_FEATURE_MASK_0(feature); + return r.flags[feature / 32] & EC_FEATURE_MASK_0(feature) ? true : + false; } /* diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c index 9324384704..7213313c1a 100644 --- a/drivers/misc/cros_ec_sandbox.c +++ b/drivers/misc/cros_ec_sandbox.c @@ -480,6 +480,17 @@ static int process_cmd(struct ec_state *ec, len = sizeof(*resp); break; } + case EC_CMD_GET_FEATURES: { + struct ec_response_get_features *resp = resp_data; + + resp->flags[0] = EC_FEATURE_MASK_0(EC_FEATURE_FLASH) | + EC_FEATURE_MASK_0(EC_FEATURE_I2C); + resp->flags[1] = + EC_FEATURE_MASK_1(EC_FEATURE_UNIFIED_WAKE_MASKS) | + EC_FEATURE_MASK_1(EC_FEATURE_ISH); + len = sizeof(*resp); + break; + } default: printf(" ** Unknown EC command %#02x\n", req_hdr->command); return -1; diff --git a/include/cros_ec.h b/include/cros_ec.h index 1154cdc52b..338878c3be 100644 --- a/include/cros_ec.h +++ b/include/cros_ec.h @@ -516,4 +516,25 @@ int cros_ec_set_lid_shutdown_mask(struct udevice *dev, int enable); * @return 0 if OK, -ve on error */ int cros_ec_hello(struct udevice *dev, uint *handshakep); + +/** + * cros_ec_get_features() - Get the set of features provided by the EC + * + * See enum ec_feature_code for the list of available features + * + * @dev: CROS-EC device + * @featuresp: Returns a bitmask of supported features + * @return 0 if OK, -ve on error + */ +int cros_ec_get_features(struct udevice *dev, u64 *featuresp); + +/** + * cros_ec_check_feature() - Check if a feature is supported + * + * @dev: CROS-EC device + * @feature: Feature number to check (enum ec_feature_code) + * @return true if supported, false if not, -ve on error + */ +int cros_ec_check_feature(struct udevice *dev, uint feature); + #endif diff --git a/include/ec_commands.h b/include/ec_commands.h index 444ba61e59..36f4a02f93 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -1101,13 +1101,50 @@ enum ec_feature_code { EC_FEATURE_DEVICE_EVENT = 31, /* EC supports the unified wake masks for LPC/eSPI systems */ EC_FEATURE_UNIFIED_WAKE_MASKS = 32, + /* EC supports 64-bit host events */ + EC_FEATURE_HOST_EVENT64 = 33, + /* EC runs code in RAM (not in place, a.k.a. XIP) */ + EC_FEATURE_EXEC_IN_RAM = 34, + /* EC supports CEC commands */ + EC_FEATURE_CEC = 35, + /* EC supports tight sensor timestamping. */ + EC_FEATURE_MOTION_SENSE_TIGHT_TIMESTAMPS = 36, + /* + * EC supports tablet mode detection aligned to Chrome and allows + * setting of threshold by host command using + * MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE. + */ + EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS = 37, + /* + * Early Firmware Selection ver.2. Enabled by CONFIG_VBOOT_EFS2. + * Note this is a RO feature. So, a query (EC_CMD_GET_FEATURES) should + * be sent to RO to be precise. + */ + EC_FEATURE_EFS2 = 38, + /* The MCU is a System Companion Processor (SCP). */ + EC_FEATURE_SCP = 39, + /* The MCU is an Integrated Sensor Hub */ + EC_FEATURE_ISH = 40, + /* New TCPMv2 TYPEC_ prefaced commands supported */ + EC_FEATURE_TYPEC_CMD = 41, + /* + * The EC will wait for direction from the AP to enter Type-C alternate + * modes or USB4. + */ + EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY = 42, + /* + * The EC will wait for an acknowledge from the AP after setting the + * mux. + */ + EC_FEATURE_TYPEC_MUX_REQUIRE_AP_ACK = 43, }; -#define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32)) -#define EC_FEATURE_MASK_1(event_code) (1UL << (event_code - 32)) -struct __ec_align4 ec_response_get_features { +#define EC_FEATURE_MASK_0(event_code) BIT(event_code % 32) +#define EC_FEATURE_MASK_1(event_code) BIT(event_code - 32) + +struct ec_response_get_features { uint32_t flags[2]; -}; +} __ec_align4; /*****************************************************************************/ /* Get the board's SKU ID from EC */ diff --git a/test/dm/cros_ec.c b/test/dm/cros_ec.c index 3d0e5dc08d..a1ec9fccf3 100644 --- a/test/dm/cros_ec.c +++ b/test/dm/cros_ec.c @@ -47,3 +47,31 @@ static int dm_test_cros_ec_sku_id(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_cros_ec_sku_id, UT_TESTF_SCAN_FDT); + +static int dm_test_cros_ec_features(struct unit_test_state *uts) +{ + struct udevice *dev; + u64 feat; + + ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev)); + ut_assertok(cros_ec_get_features(dev, &feat)); + ut_asserteq_64(1U << EC_FEATURE_FLASH | 1U << EC_FEATURE_I2C | + 1ULL << EC_FEATURE_UNIFIED_WAKE_MASKS | 1ULL << EC_FEATURE_ISH, + feat); + + ut_asserteq(true, cros_ec_check_feature(dev, EC_FEATURE_I2C)); + ut_asserteq(false, cros_ec_check_feature(dev, EC_FEATURE_MOTION_SENSE)); + ut_asserteq(true, cros_ec_check_feature(dev, EC_FEATURE_ISH)); + + /* try the command */ + console_record_reset(); + ut_assertok(run_command("crosec features", 0)); + ut_assert_nextline("flash"); + ut_assert_nextline("i2c"); + ut_assert_nextline("unified_wake_masks"); + ut_assert_nextline("ish"); + ut_assert_console_end(); + + return 0; +} +DM_TEST(dm_test_cros_ec_features, UT_TESTF_SCAN_FDT);