cros_ec: Add support for switches
authorSimon Glass <sjg@chromium.org>
Sat, 16 Jan 2021 21:52:28 +0000 (14:52 -0700)
committerSimon Glass <sjg@chromium.org>
Sat, 30 Jan 2021 21:25:41 +0000 (14:25 -0700)
On x86 platforms the EC provides a way to read 'switches', which are
on/off values determined by the EC.

Add a new driver method for this and implement it for LPC.

Signed-off-by: Simon Glass <sjg@chromium.org>
arch/sandbox/include/asm/test.h
cmd/cros_ec.c
drivers/misc/cros_ec.c
drivers/misc/cros_ec_lpc.c
drivers/misc/cros_ec_sandbox.c
include/cros_ec.h
test/dm/cros_ec.c

index 8363ca7..1cb960a 100644 (file)
@@ -61,6 +61,7 @@ enum {
  */
 enum cros_ec_test_t {
        CROSECT_BREAK_HELLO     = BIT(1),
+       CROSECT_LID_OPEN        = BIT(2),
 };
 
 /**
index 77656a2..a222c75 100644 (file)
@@ -162,6 +162,41 @@ static int do_show_features(struct udevice *dev)
        return 0;
 }
 
+static const char *const switch_name[8] = {
+       "lid open",
+       "power button pressed",
+       "write-protect disabled",
+       NULL,
+       "dedicated recovery",
+       NULL,
+       NULL,
+       NULL,
+};
+
+static int do_show_switches(struct udevice *dev)
+{
+       uint switches;
+       int ret;
+       uint i;
+
+       ret = cros_ec_get_switches(dev);
+       if (ret < 0)
+               return log_msg_ret("get", ret);
+       switches = ret;
+       for (i = 0; i < ARRAY_SIZE(switch_name); i++) {
+               uint mask = 1 << i;
+
+               if (switches & mask) {
+                       if (switch_name[i])
+                               printf("%s\n", switch_name[i]);
+                       else
+                               printf("unknown %02x\n", mask);
+               }
+       }
+
+       return 0;
+}
+
 static int do_cros_ec(struct cmd_tbl *cmdtp, int flag, int argc,
                      char *const argv[])
 {
@@ -211,6 +246,11 @@ static int do_cros_ec(struct cmd_tbl *cmdtp, int flag, int argc,
        } else if (!strcmp("features", cmd)) {
                ret = do_show_features(dev);
 
+               if (ret)
+                       printf("Error: %d\n", ret);
+       } else if (!strcmp("switches", cmd)) {
+               ret = do_show_switches(dev);
+
                if (ret)
                        printf("Error: %d\n", ret);
        } else if (0 == strcmp("curimage", cmd)) {
@@ -453,6 +493,7 @@ U_BOOT_CMD(
        "crosec id                  Read CROS-EC ID\n"
        "crosec info                Read CROS-EC info\n"
        "crosec features            Read CROS-EC features\n"
+       "crosec switches            Read CROS-EC switches\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"
index fd2f2ab..0bc28e8 100644 (file)
@@ -1557,6 +1557,22 @@ int cros_ec_set_lid_shutdown_mask(struct udevice *dev, int enable)
        return 0;
 }
 
+int cros_ec_get_switches(struct udevice *dev)
+{
+       struct dm_cros_ec_ops *ops;
+       int ret;
+
+       ops = dm_cros_ec_get_ops(dev);
+       if (!ops->get_switches)
+               return -ENOSYS;
+
+       ret = ops->get_switches(dev);
+       if (ret < 0)
+               return log_msg_ret("get", ret);
+
+       return ret;
+}
+
 UCLASS_DRIVER(cros_ec) = {
        .id             = UCLASS_CROS_EC,
        .name           = "cros-ec",
index e0002b9..f403759 100644 (file)
@@ -207,6 +207,12 @@ int cros_ec_lpc_init(struct cros_ec_dev *dev, const void *blob)
        return 0;
 }
 
+/* Return the byte of EC switch states */
+static int cros_ec_lpc_get_switches(struct udevice *dev)
+{
+       return inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES);
+}
+
 /*
  * Test if LPC command args are supported.
  *
@@ -239,6 +245,7 @@ static struct dm_cros_ec_ops cros_ec_ops = {
        .packet = cros_ec_lpc_packet,
        .command = cros_ec_lpc_command,
        .check_version = cros_ec_lpc_check_version,
+       .get_switches = cros_ec_lpc_get_switches,
 };
 
 static const struct udevice_id cros_ec_ids[] = {
index 7213313..38a2614 100644 (file)
@@ -75,6 +75,7 @@ struct ec_keymatrix_entry {
  * @keyscan: Current keyscan information (bit set for each row/column pressed)
  * @recovery_req: Keyboard recovery requested
  * @test_flags: Flags that control behaviour for tests
+ * @switches: Current switches value (EC_SWITCH_)
  */
 struct ec_state {
        u8 vbnv_context[EC_VBNV_BLOCK_SIZE_V2];
@@ -541,6 +542,14 @@ void cros_ec_check_keyboard(struct udevice *dev)
        }
 }
 
+/* Return the byte of EC switch states */
+static int cros_ec_sandbox_get_switches(struct udevice *dev)
+{
+       struct ec_state *ec = dev_get_priv(dev);
+
+       return ec->test_flags & CROSECT_LID_OPEN ? EC_SWITCH_LID_OPEN : 0;
+}
+
 void sandbox_cros_ec_set_test_flags(struct udevice *dev, uint flags)
 {
        struct ec_state *ec = dev_get_priv(dev);
@@ -603,6 +612,7 @@ int cros_ec_probe(struct udevice *dev)
 
 struct dm_cros_ec_ops cros_ec_ops = {
        .packet = cros_ec_sandbox_packet,
+       .get_switches = cros_ec_sandbox_get_switches,
 };
 
 static const struct udevice_id cros_ec_ids[] = {
index 26e3f3b..cb91343 100644 (file)
@@ -279,6 +279,16 @@ struct dm_cros_ec_ops {
         * @return number of bytes in response, or -ve on error
         */
        int (*packet)(struct udevice *dev, int out_bytes, int in_bytes);
+
+       /**
+        * get_switches() - Get value of EC switches
+        *
+        * This is currently supported on the LPC EC.
+        *
+        * @dev: Device to use
+        * @return current switches value, or -ENOSYS if not supported
+        */
+       int (*get_switches)(struct udevice *dev);
 };
 
 #define dm_cros_ec_get_ops(dev) \
@@ -577,4 +587,13 @@ int cros_ec_get_features(struct udevice *dev, u64 *featuresp);
  */
 int cros_ec_check_feature(struct udevice *dev, uint feature);
 
+/**
+ * cros_ec_get_switches() - Get switches value
+ *
+ * @dev: CROS-EC device
+ * @return switches value, or -ENOSYS if not supported, or other -ve value on
+ *     other error
+ */
+int cros_ec_get_switches(struct udevice *dev);
+
 #endif
index a1ec9fc..4377440 100644 (file)
@@ -75,3 +75,29 @@ static int dm_test_cros_ec_features(struct unit_test_state *uts)
        return 0;
 }
 DM_TEST(dm_test_cros_ec_features, UT_TESTF_SCAN_FDT);
+
+static int dm_test_cros_ec_switches(struct unit_test_state *uts)
+{
+       struct udevice *dev;
+
+       ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
+       ut_asserteq(0, cros_ec_get_switches(dev));
+
+       /* try the command */
+       console_record_reset();
+       ut_assertok(run_command("crosec switches", 0));
+       ut_assert_console_end();
+
+       /* Open the lid and check the switch changes */
+       sandbox_cros_ec_set_test_flags(dev, CROSECT_LID_OPEN);
+       ut_asserteq(EC_SWITCH_LID_OPEN, cros_ec_get_switches(dev));
+
+       /* try the command */
+       console_record_reset();
+       ut_assertok(run_command("crosec switches", 0));
+       ut_assert_nextline("lid open");
+       ut_assert_console_end();
+
+       return 0;
+}
+DM_TEST(dm_test_cros_ec_switches, UT_TESTF_SCAN_FDT);