mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-06-09 23:36:03 +09:00
cros_ec: Add support for switches
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>
This commit is contained in:
parent
2b4b653391
commit
3a6c994f38
|
@ -61,6 +61,7 @@ enum {
|
||||||
*/
|
*/
|
||||||
enum cros_ec_test_t {
|
enum cros_ec_test_t {
|
||||||
CROSECT_BREAK_HELLO = BIT(1),
|
CROSECT_BREAK_HELLO = BIT(1),
|
||||||
|
CROSECT_LID_OPEN = BIT(2),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -162,6 +162,41 @@ static int do_show_features(struct udevice *dev)
|
||||||
return 0;
|
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,
|
static int do_cros_ec(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
char *const argv[])
|
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)) {
|
} else if (!strcmp("features", cmd)) {
|
||||||
ret = do_show_features(dev);
|
ret = do_show_features(dev);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
printf("Error: %d\n", ret);
|
||||||
|
} else if (!strcmp("switches", cmd)) {
|
||||||
|
ret = do_show_switches(dev);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
printf("Error: %d\n", ret);
|
printf("Error: %d\n", ret);
|
||||||
} else if (0 == strcmp("curimage", cmd)) {
|
} else if (0 == strcmp("curimage", cmd)) {
|
||||||
|
@ -453,6 +493,7 @@ U_BOOT_CMD(
|
||||||
"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 features Read CROS-EC features\n"
|
||||||
|
"crosec switches Read CROS-EC switches\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"
|
||||||
|
|
|
@ -1557,6 +1557,22 @@ int cros_ec_set_lid_shutdown_mask(struct udevice *dev, int enable)
|
||||||
return 0;
|
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) = {
|
UCLASS_DRIVER(cros_ec) = {
|
||||||
.id = UCLASS_CROS_EC,
|
.id = UCLASS_CROS_EC,
|
||||||
.name = "cros-ec",
|
.name = "cros-ec",
|
||||||
|
|
|
@ -207,6 +207,12 @@ int cros_ec_lpc_init(struct cros_ec_dev *dev, const void *blob)
|
||||||
return 0;
|
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.
|
* 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,
|
.packet = cros_ec_lpc_packet,
|
||||||
.command = cros_ec_lpc_command,
|
.command = cros_ec_lpc_command,
|
||||||
.check_version = cros_ec_lpc_check_version,
|
.check_version = cros_ec_lpc_check_version,
|
||||||
|
.get_switches = cros_ec_lpc_get_switches,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct udevice_id cros_ec_ids[] = {
|
static const struct udevice_id cros_ec_ids[] = {
|
||||||
|
|
|
@ -75,6 +75,7 @@ struct ec_keymatrix_entry {
|
||||||
* @keyscan: Current keyscan information (bit set for each row/column pressed)
|
* @keyscan: Current keyscan information (bit set for each row/column pressed)
|
||||||
* @recovery_req: Keyboard recovery requested
|
* @recovery_req: Keyboard recovery requested
|
||||||
* @test_flags: Flags that control behaviour for tests
|
* @test_flags: Flags that control behaviour for tests
|
||||||
|
* @switches: Current switches value (EC_SWITCH_)
|
||||||
*/
|
*/
|
||||||
struct ec_state {
|
struct ec_state {
|
||||||
u8 vbnv_context[EC_VBNV_BLOCK_SIZE_V2];
|
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)
|
void sandbox_cros_ec_set_test_flags(struct udevice *dev, uint flags)
|
||||||
{
|
{
|
||||||
struct ec_state *ec = dev_get_priv(dev);
|
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 = {
|
struct dm_cros_ec_ops cros_ec_ops = {
|
||||||
.packet = cros_ec_sandbox_packet,
|
.packet = cros_ec_sandbox_packet,
|
||||||
|
.get_switches = cros_ec_sandbox_get_switches,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct udevice_id cros_ec_ids[] = {
|
static const struct udevice_id cros_ec_ids[] = {
|
||||||
|
|
|
@ -279,6 +279,16 @@ struct dm_cros_ec_ops {
|
||||||
* @return number of bytes in response, or -ve on error
|
* @return number of bytes in response, or -ve on error
|
||||||
*/
|
*/
|
||||||
int (*packet)(struct udevice *dev, int out_bytes, int in_bytes);
|
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) \
|
#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);
|
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
|
#endif
|
||||||
|
|
|
@ -75,3 +75,29 @@ static int dm_test_cros_ec_features(struct unit_test_state *uts)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
DM_TEST(dm_test_cros_ec_features, UT_TESTF_SCAN_FDT);
|
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);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user