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:
parent
7791df576c
commit
8aec32f6ab
@ -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"
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user