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 <sjg@chromium.org>
This commit is contained in:
Simon Glass 2021-01-16 14:52:26 -07:00
parent 7791df576c
commit 8aec32f6ab
6 changed files with 195 additions and 10 deletions

View File

@ -94,6 +94,74 @@ static int do_read_write(struct udevice *dev, int is_write, int argc,
return 0; 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, static int do_cros_ec(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[]) 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("rows = %u\n", info.rows);
printf("cols = %u\n", info.cols); 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)) { } else if (0 == strcmp("curimage", cmd)) {
enum ec_current_image image; enum ec_current_image image;
@ -379,6 +452,7 @@ U_BOOT_CMD(
"init Re-init CROS-EC (done on startup automatically)\n" "init Re-init CROS-EC (done on startup automatically)\n"
"crosec id Read CROS-EC ID\n" "crosec id Read CROS-EC ID\n"
"crosec info Read CROS-EC info\n" "crosec info Read CROS-EC info\n"
"crosec features Read CROS-EC features\n"
"crosec curimage Read CROS-EC current image\n" "crosec curimage Read CROS-EC current image\n"
"crosec hash Read CROS-EC hash\n" "crosec hash Read CROS-EC hash\n"
"crosec reboot [rw | ro | cold] Reboot CROS-EC\n" "crosec reboot [rw | ro | cold] Reboot CROS-EC\n"

View File

@ -1344,19 +1344,33 @@ int cros_ec_i2c_tunnel(struct udevice *dev, int port, struct i2c_msg *in,
return 0; 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; struct ec_response_get_features r;
int rv; int rv;
rv = ec_command(dev, EC_CMD_GET_FEATURES, 0, &r, sizeof(r), NULL, 0); rv = ec_command(dev, EC_CMD_GET_FEATURES, 0, NULL, 0, &r, sizeof(r));
if (rv) if (rv != sizeof(r))
return rv; 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)) 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;
} }
/* /*

View File

@ -480,6 +480,17 @@ static int process_cmd(struct ec_state *ec,
len = sizeof(*resp); len = sizeof(*resp);
break; 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: default:
printf(" ** Unknown EC command %#02x\n", req_hdr->command); printf(" ** Unknown EC command %#02x\n", req_hdr->command);
return -1; return -1;

View File

@ -516,4 +516,25 @@ int cros_ec_set_lid_shutdown_mask(struct udevice *dev, int enable);
* @return 0 if OK, -ve on error * @return 0 if OK, -ve on error
*/ */
int cros_ec_hello(struct udevice *dev, uint *handshakep); 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 #endif

View File

@ -1101,13 +1101,50 @@ enum ec_feature_code {
EC_FEATURE_DEVICE_EVENT = 31, EC_FEATURE_DEVICE_EVENT = 31,
/* EC supports the unified wake masks for LPC/eSPI systems */ /* EC supports the unified wake masks for LPC/eSPI systems */
EC_FEATURE_UNIFIED_WAKE_MASKS = 32, 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_0(event_code) BIT(event_code % 32)
#define EC_FEATURE_MASK_1(event_code) (1UL << (event_code - 32)) #define EC_FEATURE_MASK_1(event_code) BIT(event_code - 32)
struct __ec_align4 ec_response_get_features {
struct ec_response_get_features {
uint32_t flags[2]; uint32_t flags[2];
}; } __ec_align4;
/*****************************************************************************/ /*****************************************************************************/
/* Get the board's SKU ID from EC */ /* Get the board's SKU ID from EC */

View File

@ -47,3 +47,31 @@ static int dm_test_cros_ec_sku_id(struct unit_test_state *uts)
return 0; return 0;
} }
DM_TEST(dm_test_cros_ec_sku_id, UT_TESTF_SCAN_FDT); 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);