From 6208975e237c9549cab50756c6291d3ecde953b7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 31 Dec 2020 09:52:12 -0700 Subject: tpm: cr50: Check for valid locality When the Cr50 starts up it doesn't have a valid locality. The driver sets it to -1 to indicate that. Tracking this allows cr50_i2c_cleanup() to avoid releasing a locality that was not claimed. However the helper functions that generate the flags use a u8 type which cannot support -1, so they return a locality of 0xff. Fix this by updating the type. With this, 'tpm startup TPM2_SU_CLEAR' works as expected. Signed-off-by: Simon Glass --- drivers/tpm/cr50_i2c.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tpm/cr50_i2c.c b/drivers/tpm/cr50_i2c.c index ce61b72d222..f53924a8fcb 100644 --- a/drivers/tpm/cr50_i2c.c +++ b/drivers/tpm/cr50_i2c.c @@ -183,23 +183,31 @@ static int cr50_i2c_write(struct udevice *dev, u8 addr, const u8 *buffer, return cr50_i2c_wait_tpm_ready(dev); } -static inline u8 tpm_access(u8 locality) +static inline u8 tpm_access(int locality) { + if (locality == -1) + locality = 0; return 0x0 | (locality << 4); } -static inline u8 tpm_sts(u8 locality) +static inline u8 tpm_sts(int locality) { + if (locality == -1) + locality = 0; return 0x1 | (locality << 4); } -static inline u8 tpm_data_fifo(u8 locality) +static inline u8 tpm_data_fifo(int locality) { + if (locality == -1) + locality = 0; return 0x5 | (locality << 4); } -static inline u8 tpm_did_vid(u8 locality) +static inline u8 tpm_did_vid(int locality) { + if (locality == -1) + locality = 0; return 0x6 | (locality << 4); } -- cgit v1.2.3 From 5372fc772ec0004297c080a0bd53f1871bd6b93a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 31 Dec 2020 09:52:13 -0700 Subject: tpm: cr50: Add a better description and more debug Update the TPM description to include the interrupt mechanicm since this is useful to know. Also add a warning if the TPM cannot be found and a debug line if it succeeds. Signed-off-by: Simon Glass --- drivers/tpm/cr50_i2c.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tpm/cr50_i2c.c b/drivers/tpm/cr50_i2c.c index f53924a8fcb..8b792409631 100644 --- a/drivers/tpm/cr50_i2c.c +++ b/drivers/tpm/cr50_i2c.c @@ -380,7 +380,6 @@ out_err: static int cr50_i2c_send(struct udevice *dev, const u8 *buf, size_t len) { struct cr50_priv *priv = dev_get_priv(dev); - int status; size_t burstcnt, limit, sent = 0; u8 tpm_go[4] = { TPM_STS_GO }; @@ -557,9 +556,23 @@ static int cr50_i2c_get_desc(struct udevice *dev, char *buf, int size) { struct dm_i2c_chip *chip = dev_get_parent_plat(dev); struct cr50_priv *priv = dev_get_priv(dev); + int len; + + len = snprintf(buf, size, "cr50 TPM 2.0 (i2c %02x id %x), ", + chip->chip_addr, priv->vendor >> 16); + if (priv->use_irq) { + len += snprintf(buf + len, size - len, "irq=%s/%ld", + priv->irq.dev->name, priv->irq.id); + } else if (dm_gpio_is_valid(&priv->ready_gpio)) { + len += snprintf(buf + len, size - len, "gpio=%s/%u", + priv->ready_gpio.dev->name, + priv->ready_gpio.offset); + } else { + len += snprintf(buf + len, size - len, "delay=%d", + TIMEOUT_NO_IRQ_US); + } - return snprintf(buf, size, "cr50 TPM 2.0 (i2c %02x id %x) irq=%d", - chip->chip_addr, priv->vendor >> 16, priv->use_irq); + return len; } static int cr50_i2c_open(struct udevice *dev) @@ -702,11 +715,12 @@ static int cr50_i2c_probe(struct udevice *dev) mdelay(10); } if (vendor != CR50_DID_VID) { - log_debug("DID_VID %08x not recognised\n", vendor); + log_warning("DID_VID %08x not recognised\n", vendor); return log_msg_ret("vendor-id", -EXDEV); } priv->vendor = vendor; priv->locality = -1; + log_debug("Cr50 ready\n"); return 0; } -- cgit v1.2.3 From 3039fc7e964c75aba700538881b8b107c6e8792b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 31 Dec 2020 09:52:14 -0700 Subject: tpm: cr50: Rename driver to work with of-platdata Update the driver name to match the compatible string, so it can work with of-platdata. Signed-off-by: Simon Glass --- drivers/tpm/cr50_i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tpm/cr50_i2c.c b/drivers/tpm/cr50_i2c.c index 8b792409631..b103a6fdc39 100644 --- a/drivers/tpm/cr50_i2c.c +++ b/drivers/tpm/cr50_i2c.c @@ -742,8 +742,8 @@ static const struct udevice_id cr50_i2c_ids[] = { { } }; -U_BOOT_DRIVER(cr50_i2c) = { - .name = "cr50_i2c", +U_BOOT_DRIVER(google_cr50) = { + .name = "google_cr50", .id = UCLASS_TPM, .of_match = cr50_i2c_ids, .ops = &cr50_i2c_ops, -- cgit v1.2.3 From d8e9a93895fb3ad710963ddef6a4cc7c43bd65f6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 16 Jan 2021 14:52:22 -0700 Subject: cros_ec: Add a function for the hello message This is used several times in this file. Put it in a function to avoid code duplication. Also add a test for this function. There are no cros_ec tests at present, so it is time to update the code. Signed-off-by: Simon Glass --- drivers/misc/cros_ec.c | 46 ++++++++++++++++++++++++++++-------------- drivers/misc/cros_ec_sandbox.c | 12 +++++++++++ 2 files changed, 43 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index f03b7d55d64..013c67e0464 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -591,6 +591,25 @@ static int cros_ec_invalidate_hash(struct udevice *dev) return 0; } +int cros_ec_hello(struct udevice *dev, uint *handshakep) +{ + struct ec_params_hello req; + struct ec_response_hello *resp; + + req.in_data = 0x12345678; + if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req), + (uint8_t **)&resp, sizeof(*resp)) < 0) + return -EIO; + if (resp->out_data != req.in_data + 0x01020304) { + printf("Received invalid handshake %x\n", resp->out_data); + if (handshakep) + *handshakep = req.in_data; + return -ENOTSYNC; + } + + return 0; +} + int cros_ec_reboot(struct udevice *dev, enum ec_reboot_cmd cmd, uint8_t flags) { struct ec_params_reboot_ec p; @@ -738,7 +757,6 @@ static int cros_ec_check_version(struct udevice *dev) { struct cros_ec_dev *cdev = dev_get_uclass_priv(dev); struct ec_params_hello req; - struct ec_response_hello *resp; struct dm_cros_ec_ops *ops; int ret; @@ -767,14 +785,14 @@ static int cros_ec_check_version(struct udevice *dev) /* Try sending a version 3 packet */ cdev->protocol_version = 3; req.in_data = 0; - if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req), - (uint8_t **)&resp, sizeof(*resp)) > 0) + ret = cros_ec_hello(dev, NULL); + if (!ret || ret == -ENOTSYNC) return 0; /* Try sending a version 2 packet */ cdev->protocol_version = 2; - if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req), - (uint8_t **)&resp, sizeof(*resp)) > 0) + ret = cros_ec_hello(dev, NULL); + if (!ret || ret == -ENOTSYNC) return 0; /* @@ -790,18 +808,16 @@ static int cros_ec_check_version(struct udevice *dev) int cros_ec_test(struct udevice *dev) { - struct ec_params_hello req; - struct ec_response_hello *resp; + uint out_data; + int ret; - req.in_data = 0x12345678; - if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req), - (uint8_t **)&resp, sizeof(*resp)) < sizeof(*resp)) { + ret = cros_ec_hello(dev, &out_data); + if (ret == -ENOTSYNC) { + printf("Received invalid handshake %x\n", out_data); + return ret; + } else if (ret) { printf("ec_command_inptr() returned error\n"); - return -1; - } - if (resp->out_data != req.in_data + 0x01020304) { - printf("Received invalid handshake %x\n", resp->out_data); - return -1; + return ret; } return 0; diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c index 9fd6cc2086c..1922a9c1b96 100644 --- a/drivers/misc/cros_ec_sandbox.c +++ b/drivers/misc/cros_ec_sandbox.c @@ -18,6 +18,7 @@ #include #include #include +#include #include /* @@ -73,6 +74,7 @@ struct ec_keymatrix_entry { * @matrix: Information about keyboard matrix * @keyscan: Current keyscan information (bit set for each row/column pressed) * @recovery_req: Keyboard recovery requested + * @test_flags: Flags that control behaviour for tests */ struct ec_state { u8 vbnv_context[EC_VBNV_BLOCK_SIZE_V2]; @@ -84,6 +86,7 @@ struct ec_state { struct ec_keymatrix_entry *matrix; /* the key matrix info */ uint8_t keyscan[KEYBOARD_COLS]; bool recovery_req; + uint test_flags; } s_state, *g_state; /** @@ -295,6 +298,8 @@ static int process_cmd(struct ec_state *ec, struct ec_response_hello *resp = resp_data; resp->out_data = req->in_data + 0x01020304; + if (ec->test_flags & CROSECT_BREAK_HELLO) + resp->out_data++; len = sizeof(*resp); break; } @@ -518,6 +523,13 @@ void cros_ec_check_keyboard(struct udevice *dev) } } +void sandbox_cros_ec_set_test_flags(struct udevice *dev, uint flags) +{ + struct ec_state *ec = dev_get_priv(dev); + + ec->test_flags = flags; +} + int cros_ec_probe(struct udevice *dev) { struct ec_state *ec = dev_get_priv(dev); -- cgit v1.2.3 From 2525e53c2766a8731ebee9d13dd491a8ba0db2cb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 16 Jan 2021 14:52:23 -0700 Subject: cros_ec: Tidy up a few delays Allow a longer time for the EC to reboot. Also use a constant for the hash delay time, so it is clear what it is for. Signed-off-by: Simon Glass --- drivers/misc/cros_ec.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index 013c67e0464..ce5fa5bee35 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -44,6 +44,10 @@ enum { CROS_EC_CMD_TIMEOUT_MS = 5000, /* Timeout waiting for a synchronous hash to be recomputed */ CROS_EC_CMD_HASH_TIMEOUT_MS = 2000, + + /* Wait 10 ms between attempts to check if EC's hash is ready */ + CROS_EC_HASH_CHECK_DELAY_MS = 10, + }; #define INVALID_HCMD 0xFF @@ -502,9 +506,10 @@ static int cros_ec_wait_on_hash_done(struct udevice *dev, start = get_timer(0); while (hash->status == EC_VBOOT_HASH_STATUS_BUSY) { - mdelay(50); /* Insert some reasonable delay */ + mdelay(CROS_EC_HASH_CHECK_DELAY_MS); p->cmd = EC_VBOOT_HASH_GET; + if (ec_command(dev, EC_CMD_VBOOT_HASH, 0, p, sizeof(*p), hash, sizeof(*hash)) < 0) return -1; @@ -622,18 +627,23 @@ int cros_ec_reboot(struct udevice *dev, enum ec_reboot_cmd cmd, uint8_t flags) return -1; if (!(flags & EC_REBOOT_FLAG_ON_AP_SHUTDOWN)) { + ulong start; + /* * EC reboot will take place immediately so delay to allow it * to complete. Note that some reboot types (EC_REBOOT_COLD) * will reboot the AP as well, in which case we won't actually * get to this point. */ - /* - * TODO(rspangler@chromium.org): Would be nice if we had a - * better way to determine when the reboot is complete. Could - * we poll a memory-mapped LPC value? - */ - udelay(50000); + mdelay(50); + start = get_timer(0); + while (cros_ec_hello(dev, NULL)) { + if (get_timer(start) > 3000) { + log_err("EC did not return from reboot\n"); + return -ETIMEDOUT; + } + mdelay(5); + } } return 0; -- cgit v1.2.3 From 698e30f7a862ae6eb4754ef0d42b8dc8cf416edd Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 16 Jan 2021 14:52:24 -0700 Subject: cros_ec: Add run-time check for input buffer overflow This should not happen in normal operation, but the EC might have a bug, so add a run-time check just in case. Signed-off-by: Simon Glass --- drivers/misc/cros_ec.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index ce5fa5bee35..e51ac874098 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -404,6 +404,8 @@ static int ec_command(struct udevice *dev, uint cmd, int cmd_version, */ if (din && in_buffer) { assert(len <= din_len); + if (len > din_len) + return -ENOSPC; memmove(din, in_buffer, len); } } -- cgit v1.2.3 From 7791df576c4e0bcb0529850e14173d028ec37275 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 16 Jan 2021 14:52:25 -0700 Subject: cros_ec: Add support for reading the SKU ID This allows reading strapping pins attached to the EC. Add an implementation for this. Signed-off-by: Simon Glass --- drivers/misc/cros_ec.c | 13 +++++++++++++ drivers/misc/cros_ec_sandbox.c | 7 +++++++ 2 files changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index e51ac874098..80709be2f15 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -1105,6 +1105,19 @@ int cros_ec_flash_update_rw(struct udevice *dev, const uint8_t *image, return 0; } +int cros_ec_get_sku_id(struct udevice *dev) +{ + struct ec_sku_id_info *r; + int ret; + + ret = ec_command_inptr(dev, EC_CMD_GET_SKU_ID, 0, NULL, 0, + (uint8_t **)&r, sizeof(*r)); + if (ret != sizeof(*r)) + return -ret; + + return r->sku_id; +} + int cros_ec_read_nvdata(struct udevice *dev, uint8_t *block, int size) { struct ec_params_vbnvcontext p; diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c index 1922a9c1b96..93243847048 100644 --- a/drivers/misc/cros_ec_sandbox.c +++ b/drivers/misc/cros_ec_sandbox.c @@ -473,6 +473,13 @@ static int process_cmd(struct ec_state *ec, len = sizeof(*resp); break; } + case EC_CMD_GET_SKU_ID: { + struct ec_sku_id_info *resp = resp_data; + + resp->sku_id = 1234; + len = sizeof(*resp); + break; + } default: printf(" ** Unknown EC command %#02x\n", req_hdr->command); return -1; -- cgit v1.2.3 From 8aec32f6abd722b141d96bc095999efa76bd0327 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 16 Jan 2021 14:52:26 -0700 Subject: 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 --- drivers/misc/cros_ec.c | 26 ++++++++++++++++++++------ drivers/misc/cros_ec_sandbox.c | 11 +++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index 80709be2f15..fd2f2abd7e8 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -1344,19 +1344,33 @@ int cros_ec_i2c_tunnel(struct udevice *dev, int port, struct i2c_msg *in, 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; } /* diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c index 93243847048..7213313c1ac 100644 --- a/drivers/misc/cros_ec_sandbox.c +++ b/drivers/misc/cros_ec_sandbox.c @@ -480,6 +480,17 @@ static int process_cmd(struct ec_state *ec, 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; -- cgit v1.2.3 From 3a6c994f3896d66e617acdf9bb58ffc4def08b71 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 16 Jan 2021 14:52:28 -0700 Subject: 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 --- drivers/misc/cros_ec.c | 16 ++++++++++++++++ drivers/misc/cros_ec_lpc.c | 7 +++++++ drivers/misc/cros_ec_sandbox.c | 10 ++++++++++ 3 files changed, 33 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index fd2f2abd7e8..0bc28e882c9 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -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", diff --git a/drivers/misc/cros_ec_lpc.c b/drivers/misc/cros_ec_lpc.c index e0002b9753f..f40375978dd 100644 --- a/drivers/misc/cros_ec_lpc.c +++ b/drivers/misc/cros_ec_lpc.c @@ -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[] = { diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c index 7213313c1ac..38a2614a993 100644 --- a/drivers/misc/cros_ec_sandbox.c +++ b/drivers/misc/cros_ec_sandbox.c @@ -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[] = { -- cgit v1.2.3 From 3ae338299e1649ef9a38c45fcde864022c448a9e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 16 Jan 2021 14:52:29 -0700 Subject: cros_ec: Show events in human-readable form Add a command to show the current events as a list of names. This is easier to decipher than a bit mask. Signed-off-by: Simon Glass --- drivers/misc/cros_ec_sandbox.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c index 38a2614a993..845876cfb0c 100644 --- a/drivers/misc/cros_ec_sandbox.c +++ b/drivers/misc/cros_ec_sandbox.c @@ -364,10 +364,20 @@ static int process_cmd(struct ec_state *ec, resp->mask |= EC_HOST_EVENT_MASK( EC_HOST_EVENT_KEYBOARD_RECOVERY); } - + if (ec->test_flags & CROSECT_LID_OPEN) + resp->mask |= + EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN); len = sizeof(*resp); break; } + case EC_CMD_HOST_EVENT_CLEAR_B: { + const struct ec_params_host_event_mask *req = req_data; + + if (req->mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN)) + ec->test_flags &= ~CROSECT_LID_OPEN; + len = 0; + break; + } case EC_CMD_VBOOT_HASH: { const struct ec_params_vboot_hash *req = req_data; struct ec_response_vboot_hash *resp = resp_data; -- cgit v1.2.3 From d9ffaef6fe25e7a29e63911fe1af5d18c9d77a45 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 16 Jan 2021 14:52:30 -0700 Subject: cros_ec: Allow use with of-platdata Avoid reading the device tree when of-platdata is in use. Signed-off-by: Simon Glass --- drivers/misc/cros_ec.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index 0bc28e882c9..c22bb4b5b50 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -1577,6 +1577,8 @@ UCLASS_DRIVER(cros_ec) = { .id = UCLASS_CROS_EC, .name = "cros-ec", .per_device_auto = sizeof(struct cros_ec_dev), +#if !CONFIG_IS_ENABLED(OF_PLATDATA) .post_bind = dm_scan_fdt_dev, +#endif .flags = DM_UC_FLAG_ALLOC_PRIV_DMA, }; -- cgit v1.2.3 From 10f746591fba16a48f0e3d14641be09f01982807 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 16 Jan 2021 14:52:31 -0700 Subject: cros_ec: Add vstore support The EC can store small amounts of data for the benefit of the verified boot process. Since the EC is seldom reset, this can allow the AP to store data that survives a reboot or a suspend/resume cycle. Add support for this. Signed-off-by: Simon Glass --- drivers/misc/cros_ec.c | 71 ++++++++++++++++++++++++++++++++++++++++++ drivers/misc/cros_ec_sandbox.c | 52 +++++++++++++++++++++++++++++-- 2 files changed, 121 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index c22bb4b5b50..ebfa7c41c25 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -1557,6 +1557,77 @@ int cros_ec_set_lid_shutdown_mask(struct udevice *dev, int enable) return 0; } +int cros_ec_vstore_supported(struct udevice *dev) +{ + return cros_ec_check_feature(dev, EC_FEATURE_VSTORE); +} + +int cros_ec_vstore_info(struct udevice *dev, u32 *lockedp) +{ + struct ec_response_vstore_info *resp; + + if (ec_command_inptr(dev, EC_CMD_VSTORE_INFO, 0, NULL, 0, + (uint8_t **)&resp, sizeof(*resp)) != sizeof(*resp)) + return -EIO; + + if (lockedp) + *lockedp = resp->slot_locked; + + return resp->slot_count; +} + +/* + * cros_ec_vstore_read - Read data from EC vstore slot + * + * @slot: vstore slot to read from + * @data: buffer to store read data, must be EC_VSTORE_SLOT_SIZE bytes + */ +int cros_ec_vstore_read(struct udevice *dev, int slot, uint8_t *data) +{ + struct ec_params_vstore_read req; + struct ec_response_vstore_read *resp; + + req.slot = slot; + if (ec_command_inptr(dev, EC_CMD_VSTORE_READ, 0, &req, sizeof(req), + (uint8_t **)&resp, sizeof(*resp)) != sizeof(*resp)) + return -EIO; + + if (!data || req.slot >= EC_VSTORE_SLOT_MAX) + return -EINVAL; + + memcpy(data, resp->data, sizeof(resp->data)); + + return 0; +} + +/* + * cros_ec_vstore_write - Save data into EC vstore slot + * + * @slot: vstore slot to write into + * @data: data to write + * @size: size of data in bytes + * + * Maximum size of data is EC_VSTORE_SLOT_SIZE. It is the callers + * responsibility to check the number of implemented slots by + * querying the vstore info. + */ +int cros_ec_vstore_write(struct udevice *dev, int slot, const uint8_t *data, + size_t size) +{ + struct ec_params_vstore_write req; + + if (slot >= EC_VSTORE_SLOT_MAX || size > EC_VSTORE_SLOT_SIZE) + return -EINVAL; + + req.slot = slot; + memcpy(req.data, data, size); + + if (ec_command(dev, EC_CMD_VSTORE_WRITE, 0, &req, sizeof(req), NULL, 0)) + return -EIO; + + return 0; +} + int cros_ec_get_switches(struct udevice *dev) { struct dm_cros_ec_ops *ops; diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c index 845876cfb0c..cb8adc4495a 100644 --- a/drivers/misc/cros_ec_sandbox.c +++ b/drivers/misc/cros_ec_sandbox.c @@ -62,6 +62,15 @@ struct ec_keymatrix_entry { int keycode; /* corresponding linux key code */ }; +enum { + VSTORE_SLOT_COUNT = 4, +}; + +struct vstore_slot { + bool locked; + u8 data[EC_VSTORE_SLOT_SIZE]; +}; + /** * struct ec_state - Information about the EC state * @@ -75,7 +84,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_) + * @slot_locked: Locked vstore slots (mask) */ struct ec_state { u8 vbnv_context[EC_VBNV_BLOCK_SIZE_V2]; @@ -88,6 +97,7 @@ struct ec_state { uint8_t keyscan[KEYBOARD_COLS]; bool recovery_req; uint test_flags; + struct vstore_slot slot[VSTORE_SLOT_COUNT]; } s_state, *g_state; /** @@ -495,13 +505,51 @@ static int process_cmd(struct ec_state *ec, 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); + EC_FEATURE_MASK_0(EC_FEATURE_I2C) | + EC_FEATURE_MASK_0(EC_FEATURE_VSTORE); resp->flags[1] = EC_FEATURE_MASK_1(EC_FEATURE_UNIFIED_WAKE_MASKS) | EC_FEATURE_MASK_1(EC_FEATURE_ISH); len = sizeof(*resp); break; } + case EC_CMD_VSTORE_INFO: { + struct ec_response_vstore_info *resp = resp_data; + int i; + + resp->slot_count = VSTORE_SLOT_COUNT; + resp->slot_locked = 0; + for (i = 0; i < VSTORE_SLOT_COUNT; i++) { + if (ec->slot[i].locked) + resp->slot_locked |= 1 << i; + } + len = sizeof(*resp); + break; + }; + case EC_CMD_VSTORE_WRITE: { + const struct ec_params_vstore_write *req = req_data; + struct vstore_slot *slot; + + if (req->slot >= EC_VSTORE_SLOT_MAX) + return -EINVAL; + slot = &ec->slot[req->slot]; + slot->locked = true; + memcpy(slot->data, req->data, EC_VSTORE_SLOT_SIZE); + len = 0; + break; + } + case EC_CMD_VSTORE_READ: { + const struct ec_params_vstore_read *req = req_data; + struct ec_response_vstore_read *resp = resp_data; + struct vstore_slot *slot; + + if (req->slot >= EC_VSTORE_SLOT_MAX) + return -EINVAL; + slot = &ec->slot[req->slot]; + memcpy(resp->data, slot->data, EC_VSTORE_SLOT_SIZE); + len = sizeof(*resp); + break; + } default: printf(" ** Unknown EC command %#02x\n", req_hdr->command); return -1; -- cgit v1.2.3 From dfb5bfbc208699ae1b5fc8e17f65d862be3b4612 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 21 Jan 2021 13:57:08 -0700 Subject: i2c: desigware: Add an alias for Intel Apollo Lake Add an alias so that this driver can be used in TPL on coral. Signed-off-by: Simon Glass Reviewed-by: Heiko Schocher --- drivers/i2c/designware_i2c_pci.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/i2c/designware_i2c_pci.c b/drivers/i2c/designware_i2c_pci.c index ec0cdf62207..9e387737b6e 100644 --- a/drivers/i2c/designware_i2c_pci.c +++ b/drivers/i2c/designware_i2c_pci.c @@ -192,6 +192,8 @@ static const struct udevice_id designware_i2c_pci_ids[] = { { } }; +DM_DRIVER_ALIAS(i2c_designware_pci, intel_apl_i2c) + U_BOOT_DRIVER(i2c_designware_pci) = { .name = "i2c_designware_pci", .id = UCLASS_I2C, -- cgit v1.2.3 From d85f2c4f2970d0ec2f5f075de734afd11200d153 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 21 Jan 2021 13:57:09 -0700 Subject: sandbox: Disable I2C emulators in SPL These cannot work with of-platdata since they currently need the devicetree at runtime. Disable the emulators and the sandbox I2C driver that needs them. We can enable these later, if needed for testing. Switch the of_plat_parent test over to use a simple bus instead. Signed-off-by: Simon Glass Reviewed-by: Heiko Schocher --- drivers/i2c/Makefile | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 1aac5c481e2..29aab0f9e30 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -39,7 +39,9 @@ obj-$(CONFIG_SYS_I2C_RCAR_I2C) += rcar_i2c.o obj-$(CONFIG_SYS_I2C_RCAR_IIC) += rcar_iic.o obj-$(CONFIG_SYS_I2C_ROCKCHIP) += rk_i2c.o obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o exynos_hs_i2c.o +ifndef CONFIG_SPL_BUILD obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o +endif obj-$(CONFIG_SYS_I2C_SH) += sh_i2c.o obj-$(CONFIG_SYS_I2C_SOFT) += soft_i2c.o obj-$(CONFIG_SYS_I2C_STM32F7) += stm32f7_i2c.o -- cgit v1.2.3 From 5c5992cb90cf9ca4d51e38d9a95a13c293904df5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 21 Jan 2021 13:57:11 -0700 Subject: clk: Add debugging for return values Use the log_msg_ret() mechanism to get error-return information when clocks fail to probe, etc. Signed-off-by: Simon Glass --- drivers/clk/clk-uclass.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index b75056718bf..d5c4e3cbe51 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -83,7 +83,7 @@ static int clk_get_by_index_tail(int ret, ofnode node, if (ret) { debug("%s: uclass_get_device_by_of_offset failed: err=%d\n", __func__, ret); - return ret; + return log_msg_ret("get", ret); } clk->dev = dev_clk; @@ -96,14 +96,15 @@ static int clk_get_by_index_tail(int ret, ofnode node, ret = clk_of_xlate_default(clk, args); if (ret) { debug("of_xlate() failed: %d\n", ret); - return ret; + return log_msg_ret("xlate", ret); } return clk_request(dev_clk, clk); err: debug("%s: Node '%s', property '%s', failed to request CLK index %d: %d\n", __func__, ofnode_get_name(node), list_name, index, ret); - return ret; + + return log_msg_ret("prop", ret); } static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name, @@ -122,7 +123,7 @@ static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name, if (ret) { debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n", __func__, ret); - return ret; + return log_ret(ret); } @@ -470,6 +471,7 @@ int clk_free(struct clk *clk) ulong clk_get_rate(struct clk *clk) { const struct clk_ops *ops; + int ret; debug("%s(clk=%p)\n", __func__, clk); if (!clk_valid(clk)) @@ -479,7 +481,11 @@ ulong clk_get_rate(struct clk *clk) if (!ops->get_rate) return -ENOSYS; - return ops->get_rate(clk); + ret = ops->get_rate(clk); + if (ret) + return log_ret(ret); + + return 0; } struct clk *clk_get_parent(struct clk *clk) -- cgit v1.2.3 From 0dc2bf2b6e6e7581e3307f3aa65d0ce310375511 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 21 Jan 2021 13:57:12 -0700 Subject: clk: x86: Correct the driver name The current driver name does not match its compatible string, so of-platdata does not work correctly. Fix it. Signed-off-by: Simon Glass --- drivers/clk/intel/clk_intel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/intel/clk_intel.c b/drivers/clk/intel/clk_intel.c index b633934d90a..46ccbb1d834 100644 --- a/drivers/clk/intel/clk_intel.c +++ b/drivers/clk/intel/clk_intel.c @@ -29,8 +29,8 @@ static const struct udevice_id intel_clk_ids[] = { { } }; -U_BOOT_DRIVER(clk_intel) = { - .name = "clk_intel", +U_BOOT_DRIVER(intel_apl_clk) = { + .name = "intel_apl_clk", .id = UCLASS_CLK, .of_match = intel_clk_ids, .ops = &intel_clk_ops, -- cgit v1.2.3 From 017d421828971f6adbfa6a1305b80da7d620c596 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 21 Jan 2021 13:57:13 -0700 Subject: dm: core: Add a comment about pinctrl_select_state() The use of pinctrl in the core of driver model is useful but can provoke some strange behaviour. Add a comment to aid debugging. Signed-off-by: Simon Glass --- drivers/core/device.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/core/device.c b/drivers/core/device.c index aeab3836ed7..8629df8defb 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -462,6 +462,15 @@ int device_probe(struct udevice *dev) * continue regardless of the result of pinctrl. Don't process pinctrl * settings for pinctrl devices since the device may not yet be * probed. + * + * This call can produce some non-intuitive results. For example, on an + * x86 device where dev is the main PCI bus, the pinctrl device may be + * child or grandchild of that bus, meaning that the child will be + * probed here. If the child happens to be the P2SB and the pinctrl + * device is a child of that, then both the pinctrl and P2SB will be + * probed by this call. This works because the DM_FLAG_ACTIVATED flag + * is set just above. However, the PCI bus' probe() method and + * associated uclass methods have not yet been called. */ if (dev->parent && device_get_uclass_id(dev) != UCLASS_PINCTRL) pinctrl_select_state(dev, "default"); -- cgit v1.2.3 From ff5fa7d62655ae6c1873e17057c057566c81df0d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 21 Jan 2021 13:57:14 -0700 Subject: dm: core: Update ofnode_read_fmap_entry() to read hashes At present this function uses the old format for reading hashes. Add support for the current format. Add a test while we are here. Signed-off-by: Simon Glass --- drivers/core/of_extra.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/core/of_extra.c b/drivers/core/of_extra.c index 6420e6ec448..653344529e6 100644 --- a/drivers/core/of_extra.c +++ b/drivers/core/of_extra.c @@ -14,16 +14,17 @@ int ofnode_read_fmap_entry(ofnode node, struct fmap_entry *entry) { const char *prop; + ofnode subnode; if (ofnode_read_u32(node, "image-pos", &entry->offset)) { debug("Node '%s' has bad/missing 'image-pos' property\n", ofnode_get_name(node)); - return log_ret(-ENOENT); + return log_msg_ret("image-pos", -ENOENT); } if (ofnode_read_u32(node, "size", &entry->length)) { debug("Node '%s' has bad/missing 'size' property\n", ofnode_get_name(node)); - return log_ret(-ENOENT); + return log_msg_ret("size", -ENOENT); } entry->used = ofnode_read_s32_default(node, "used", entry->length); prop = ofnode_read_string(node, "compress"); @@ -31,18 +32,20 @@ int ofnode_read_fmap_entry(ofnode node, struct fmap_entry *entry) if (!strcmp(prop, "lz4")) entry->compress_algo = FMAP_COMPRESS_LZ4; else - return log_msg_ret("Unknown compression algo", - -EINVAL); + return log_msg_ret("compression algo", -EINVAL); } else { entry->compress_algo = FMAP_COMPRESS_NONE; } entry->unc_length = ofnode_read_s32_default(node, "uncomp-size", entry->length); - prop = ofnode_read_string(node, "hash"); - if (prop) - entry->hash_size = strlen(prop); - entry->hash_algo = prop ? FMAP_HASH_SHA256 : FMAP_HASH_NONE; - entry->hash = (uint8_t *)prop; + subnode = ofnode_find_subnode(node, "hash"); + if (ofnode_valid(subnode)) { + prop = ofnode_read_prop(subnode, "value", &entry->hash_size); + + /* Assume it is sha256 */ + entry->hash_algo = prop ? FMAP_HASH_SHA256 : FMAP_HASH_NONE; + entry->hash = (uint8_t *)prop; + } return 0; } -- cgit v1.2.3 From 43db07507abdb54b6575345300c171b0486e46be Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 30 Dec 2020 18:07:48 +0100 Subject: sandbox: keep time offset when resetting The UEFI Self Certification Test (SCT) checks the SetTime() service with the following steps: * set date * reset * check date matches To be compliant the sandbox should keep the offset to the host RTC during resets. The implementation uses the environment variable UBOOT_SB_TIME_OFFSET to persist the offset. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass --- drivers/rtc/i2c_rtc_emul.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/i2c_rtc_emul.c b/drivers/rtc/i2c_rtc_emul.c index 5a2a154e653..f25b976e54d 100644 --- a/drivers/rtc/i2c_rtc_emul.c +++ b/drivers/rtc/i2c_rtc_emul.c @@ -57,6 +57,7 @@ long sandbox_i2c_rtc_set_offset(struct udevice *dev, bool use_system_time, plat->use_system_time = use_system_time; if (offset != -1) plat->offset = offset; + os_set_time_offset(plat->offset); return old_offset; } @@ -80,7 +81,7 @@ static void reset_time(struct udevice *dev) os_localtime(&now); plat->base_time = rtc_mktime(&now); - plat->offset = 0; + plat->offset = os_get_time_offset(); plat->use_system_time = true; } @@ -115,6 +116,7 @@ static int sandbox_i2c_rtc_set(struct udevice *dev, const struct rtc_time *time) now = plat->base_time; } plat->offset = rtc_mktime(time) - now; + os_set_time_offset(plat->offset); return 0; } -- cgit v1.2.3 From 168e313b5b128a0a2e55010875c1636dead38527 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Mon, 25 Jan 2021 12:57:14 +0100 Subject: sandbox: fill block device meta information Provide information about host backed block device. Mark the device created by 'host bind' as removable. Signed-off-by: Heinrich Schuchardt --- drivers/block/sandbox.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c index 34c26cda47e..f57f690d3c0 100644 --- a/drivers/block/sandbox.c +++ b/drivers/block/sandbox.c @@ -92,6 +92,7 @@ int host_dev_bind(int devnum, char *filename) { struct host_block_dev *host_dev; struct udevice *dev; + struct blk_desc *desc; char dev_name[20], *str, *fname; int ret, fd; @@ -143,6 +144,12 @@ int host_dev_bind(int devnum, char *filename) goto err_file; } + desc = blk_get_devnum_by_type(IF_TYPE_HOST, devnum); + desc->removable = 1; + snprintf(desc->vendor, BLK_VEN_SIZE, "U-Boot"); + snprintf(desc->product, BLK_PRD_SIZE, "hostfile"); + snprintf(desc->revision, BLK_REV_SIZE, "1.0"); + return 0; err_file: os_close(fd); @@ -187,6 +194,10 @@ int host_dev_bind(int dev, char *filename) blk_dev->block_write = host_block_write; blk_dev->devnum = dev; blk_dev->part_type = PART_TYPE_UNKNOWN; + blk_dev->removable = 1; + snprintf(blk_dev->vendor, BLK_VEN_SIZE, "U-Boot"); + snprintf(blk_dev->product, BLK_PRD_SIZE, "hostfile"); + snprintf(blk_dev->revision, BLK_REV_SIZE, "1.0"); part_init(blk_dev); return 0; -- cgit v1.2.3