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[])
{
}
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;
"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"
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;
}
/*
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;
* @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
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 */
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);