diff options
| author | Mark Brown <broonie@kernel.org> | 2026-09-07 14:28:16 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-09-07 14:28:16 +0100 |
| commit | 981b728ec491034bedcca0f1b6b5933d767faba6 (patch) | |
| tree | 9e0dac915f8330347ef62f8f861017886dc50137 | |
| parent | f36faf29a1d5e0625fa01269541e3c70beaf655a (diff) | |
| parent | 5859f97c6f404d07e89fe9c0d20a318ebf200bd1 (diff) | |
| download | linux-next-981b728ec491034bedcca0f1b6b5933d767faba6.tar.gz linux-next-981b728ec491034bedcca0f1b6b5933d767faba6.zip | |
Merge branch 'for-next' of https://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux.git
| -rw-r--r-- | drivers/platform/chrome/cros_ec_ishtp.c | 2 | ||||
| -rw-r--r-- | drivers/platform/chrome/cros_ec_proto.c | 43 | ||||
| -rw-r--r-- | drivers/platform/chrome/cros_ec_proto_test.c | 158 | ||||
| -rw-r--r-- | drivers/platform/chrome/cros_ec_rpmsg.c | 2 | ||||
| -rw-r--r-- | drivers/platform/chrome/cros_usbpd_notify.c | 4 | ||||
| -rw-r--r-- | include/linux/platform_data/cros_ec_commands.h | 72 |
6 files changed, 262 insertions, 19 deletions
diff --git a/drivers/platform/chrome/cros_ec_ishtp.c b/drivers/platform/chrome/cros_ec_ishtp.c index 3766cef81fe8..b21a27ad3762 100644 --- a/drivers/platform/chrome/cros_ec_ishtp.c +++ b/drivers/platform/chrome/cros_ec_ishtp.c @@ -369,7 +369,7 @@ static void ish_event_cb(struct ishtp_cl_device *cl_device) * @cros_ish_cl: ISHTP client instance * @reset: true if called from reset handler * - * This function complete the initializtion of the client. + * This function complete the initialization of the client. * * Return: 0 for success, negative error code for failure. */ diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index 724d1313f6b2..b81b37c7169a 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -138,7 +138,8 @@ static int cros_ec_xfer_command(struct cros_ec_device *ec_dev, struct cros_ec_co return ret; } -static int cros_ec_wait_until_complete(struct cros_ec_device *ec_dev, uint32_t *result) +static int cros_ec_wait_until_complete(struct cros_ec_device *ec_dev, + struct cros_ec_command *orig_msg) { DEFINE_RAW_FLEX(struct cros_ec_command, msg, data, sizeof(struct ec_response_get_comms_status)); @@ -161,23 +162,41 @@ static int cros_ec_wait_until_complete(struct cros_ec_device *ec_dev, uint32_t * if (ret < 0) return ret; - *result = msg->result; + orig_msg->result = msg->result; if (msg->result != EC_RES_SUCCESS) return ret; - if (ret == 0) { - ret = -EPROTO; - break; - } + if (ret == 0) + return -EPROTO; + + if (!(status->flags & EC_COMMS_STATUS_PROCESSING)) { + u32 orig_cmd, orig_outsize, orig_version; + + /* If no response payload is expected, return 0. */ + if (orig_msg->insize == 0) + return 0; - if (!(status->flags & EC_COMMS_STATUS_PROCESSING)) + /* + * Request the response using EC_CMD_RESEND_RESPONSE. + * Restore the original message fields so it appears + * to be a direct response to the original command. + */ + orig_cmd = orig_msg->command; + orig_outsize = orig_msg->outsize; + orig_version = orig_msg->version; + + orig_msg->command = EC_CMD_RESEND_RESPONSE; + orig_msg->outsize = 0; + orig_msg->version = 0; + ret = cros_ec_xfer_command(ec_dev, orig_msg); + orig_msg->command = orig_cmd; + orig_msg->outsize = orig_outsize; + orig_msg->version = orig_version; return ret; + } } - if (i >= EC_COMMAND_RETRIES) - ret = -EAGAIN; - - return ret; + return -EAGAIN; } static int cros_ec_send_command(struct cros_ec_device *ec_dev, struct cros_ec_command *msg) @@ -185,7 +204,7 @@ static int cros_ec_send_command(struct cros_ec_device *ec_dev, struct cros_ec_co int ret = cros_ec_xfer_command(ec_dev, msg); if (msg->result == EC_RES_IN_PROGRESS) - ret = cros_ec_wait_until_complete(ec_dev, &msg->result); + ret = cros_ec_wait_until_complete(ec_dev, msg); return ret; } diff --git a/drivers/platform/chrome/cros_ec_proto_test.c b/drivers/platform/chrome/cros_ec_proto_test.c index 3f281996a686..cbaaf98d6877 100644 --- a/drivers/platform/chrome/cros_ec_proto_test.c +++ b/drivers/platform/chrome/cros_ec_proto_test.c @@ -1744,7 +1744,7 @@ static void cros_ec_proto_test_cmd_xfer_protocol_v2_no_op(struct kunit *test) KUNIT_EXPECT_EQ(test, ret, -EIO); } -static void cros_ec_proto_test_cmd_xfer_in_progress_normal(struct kunit *test) +static void cros_ec_proto_test_cmd_xfer_in_progress_payload_0byte(struct kunit *test) { struct cros_ec_proto_test_priv *priv = test->priv; struct cros_ec_device *ec_dev = &priv->ec_dev; @@ -1774,7 +1774,7 @@ static void cros_ec_proto_test_cmd_xfer_in_progress_normal(struct kunit *test) } ret = cros_ec_cmd_xfer(ec_dev, &msg); - KUNIT_EXPECT_EQ(test, ret, sizeof(struct ec_response_get_comms_status)); + KUNIT_EXPECT_EQ(test, ret, 0); KUNIT_EXPECT_EQ(test, msg.result, EC_RES_SUCCESS); @@ -1799,6 +1799,156 @@ static void cros_ec_proto_test_cmd_xfer_in_progress_normal(struct kunit *test) KUNIT_EXPECT_EQ(test, cros_kunit_ec_pkt_xfer_mock_called, 2); } +static void cros_ec_proto_test_cmd_xfer_in_progress_payload_4bytes(struct kunit *test) +{ + struct cros_ec_proto_test_priv *priv = test->priv; + struct cros_ec_device *ec_dev = &priv->ec_dev; + struct ec_xfer_mock *mock; + u8 resp_data[4] = {0x11, 0x22, 0x33, 0x44}; + struct { + struct cros_ec_command msg; + u8 data[4]; + } buf; + struct cros_ec_command *msg = &buf.msg; + int ret; + + memset(&buf, 0, sizeof(buf)); + msg->version = 1; + msg->command = 0x1234; + msg->insize = sizeof(buf.data); + + ec_dev->max_response = sizeof(buf.data); + ec_dev->pkt_xfer = cros_kunit_ec_pkt_xfer_mock; + + /* For initial command returning EC_RES_IN_PROGRESS. */ + { + mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_IN_PROGRESS, 0); + KUNIT_ASSERT_PTR_NE(test, mock, NULL); + } + + /* For EC_CMD_GET_COMMS_STATUS status polling. */ + { + struct ec_response_get_comms_status *data; + + mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data)); + KUNIT_ASSERT_PTR_NE(test, mock, NULL); + + data = (struct ec_response_get_comms_status *)mock->o_data; + data->flags = 0; + } + + /* For EC_CMD_RESEND_RESPONSE returning 4 bytes payload. */ + { + mock = cros_kunit_ec_xfer_mock_add(test, sizeof(resp_data)); + KUNIT_ASSERT_PTR_NE(test, mock, NULL); + memcpy(mock->o_data, resp_data, sizeof(resp_data)); + } + + ret = cros_ec_cmd_xfer(ec_dev, msg); + KUNIT_EXPECT_EQ(test, ret, 4); + KUNIT_EXPECT_EQ(test, msg->result, EC_RES_SUCCESS); + KUNIT_EXPECT_EQ(test, msg->command, 0x1234); + KUNIT_EXPECT_EQ(test, msg->insize, sizeof(buf.data)); + KUNIT_EXPECT_EQ(test, msg->version, 1); + KUNIT_EXPECT_EQ(test, memcmp(msg->data, resp_data, sizeof(resp_data)), 0); + + /* Verify mock sequence */ + { + mock = cros_kunit_ec_xfer_mock_next(); + KUNIT_EXPECT_PTR_NE(test, mock, NULL); + + mock = cros_kunit_ec_xfer_mock_next(); + KUNIT_EXPECT_PTR_NE(test, mock, NULL); + KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_COMMS_STATUS); + + mock = cros_kunit_ec_xfer_mock_next(); + KUNIT_EXPECT_PTR_NE(test, mock, NULL); + KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_RESEND_RESPONSE); + KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0); + KUNIT_EXPECT_EQ(test, mock->msg.version, 0); + KUNIT_EXPECT_EQ(test, mock->msg.insize, 4); + } + + KUNIT_EXPECT_EQ(test, cros_kunit_ec_pkt_xfer_mock_called, 3); +} + +static void cros_ec_proto_test_cmd_xfer_in_progress_payload_gt4bytes(struct kunit *test) +{ + struct cros_ec_proto_test_priv *priv = test->priv; + struct cros_ec_device *ec_dev = &priv->ec_dev; + struct ec_xfer_mock *mock; + u8 resp_data[16]; + struct { + struct cros_ec_command msg; + u8 data[16]; + } buf; + struct cros_ec_command *msg = &buf.msg; + int ret, i; + + for (i = 0; i < sizeof(resp_data); ++i) + resp_data[i] = (u8)(i + 1); + + memset(&buf, 0, sizeof(buf)); + msg->version = 0; + msg->command = 0x5678; + msg->insize = sizeof(buf.data); + + ec_dev->max_response = sizeof(buf.data); + ec_dev->pkt_xfer = cros_kunit_ec_pkt_xfer_mock; + + /* For initial command returning EC_RES_IN_PROGRESS. */ + { + mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_IN_PROGRESS, 0); + KUNIT_ASSERT_PTR_NE(test, mock, NULL); + } + + /* For EC_CMD_GET_COMMS_STATUS status polling. */ + { + struct ec_response_get_comms_status *data; + + mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data)); + KUNIT_ASSERT_PTR_NE(test, mock, NULL); + + data = (struct ec_response_get_comms_status *)mock->o_data; + data->flags = 0; + } + + /* For EC_CMD_RESEND_RESPONSE returning 16 bytes payload. */ + { + mock = cros_kunit_ec_xfer_mock_add(test, sizeof(resp_data)); + KUNIT_ASSERT_PTR_NE(test, mock, NULL); + memcpy(mock->o_data, resp_data, sizeof(resp_data)); + } + + ret = cros_ec_cmd_xfer(ec_dev, msg); + KUNIT_EXPECT_EQ(test, ret, 16); + KUNIT_EXPECT_EQ(test, msg->result, EC_RES_SUCCESS); + KUNIT_EXPECT_EQ(test, msg->command, 0x5678); + KUNIT_EXPECT_EQ(test, msg->outsize, 0); + KUNIT_EXPECT_EQ(test, msg->insize, sizeof(buf.data)); + KUNIT_EXPECT_EQ(test, msg->version, 0); + KUNIT_EXPECT_EQ(test, memcmp(msg->data, resp_data, sizeof(resp_data)), 0); + + /* Verify mock sequence */ + { + mock = cros_kunit_ec_xfer_mock_next(); + KUNIT_EXPECT_PTR_NE(test, mock, NULL); + + mock = cros_kunit_ec_xfer_mock_next(); + KUNIT_EXPECT_PTR_NE(test, mock, NULL); + KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_COMMS_STATUS); + + mock = cros_kunit_ec_xfer_mock_next(); + KUNIT_EXPECT_PTR_NE(test, mock, NULL); + KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_RESEND_RESPONSE); + KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0); + KUNIT_EXPECT_EQ(test, mock->msg.version, 0); + KUNIT_EXPECT_EQ(test, mock->msg.insize, 16); + } + + KUNIT_EXPECT_EQ(test, cros_kunit_ec_pkt_xfer_mock_called, 3); +} + static void cros_ec_proto_test_cmd_xfer_in_progress_retries_eagain(struct kunit *test) { struct cros_ec_proto_test_priv *priv = test->priv; @@ -2703,7 +2853,9 @@ static struct kunit_case cros_ec_proto_test_cases[] = { KUNIT_CASE(cros_ec_proto_test_cmd_xfer_protocol_v3_no_op), KUNIT_CASE(cros_ec_proto_test_cmd_xfer_protocol_v2_normal), KUNIT_CASE(cros_ec_proto_test_cmd_xfer_protocol_v2_no_op), - KUNIT_CASE(cros_ec_proto_test_cmd_xfer_in_progress_normal), + KUNIT_CASE(cros_ec_proto_test_cmd_xfer_in_progress_payload_0byte), + KUNIT_CASE(cros_ec_proto_test_cmd_xfer_in_progress_payload_4bytes), + KUNIT_CASE(cros_ec_proto_test_cmd_xfer_in_progress_payload_gt4bytes), KUNIT_CASE(cros_ec_proto_test_cmd_xfer_in_progress_retries_eagain), KUNIT_CASE(cros_ec_proto_test_cmd_xfer_in_progress_retries_status_processing), KUNIT_CASE(cros_ec_proto_test_cmd_xfer_in_progress_xfer_error), diff --git a/drivers/platform/chrome/cros_ec_rpmsg.c b/drivers/platform/chrome/cros_ec_rpmsg.c index 09bd9e49464e..7390c2c91ea5 100644 --- a/drivers/platform/chrome/cros_ec_rpmsg.c +++ b/drivers/platform/chrome/cros_ec_rpmsg.c @@ -20,7 +20,7 @@ #define HOST_EVENT_MARK 2 /** - * struct cros_ec_rpmsg_response - rpmsg message format from from EC. + * struct cros_ec_rpmsg_response - rpmsg message format from EC. * * @type: The type of message, should be either HOST_COMMAND_MARK or * HOST_EVENT_MARK, representing that the message is a response to diff --git a/drivers/platform/chrome/cros_usbpd_notify.c b/drivers/platform/chrome/cros_usbpd_notify.c index d842c05f4db0..6f5eea4938cb 100644 --- a/drivers/platform/chrome/cros_usbpd_notify.c +++ b/drivers/platform/chrome/cros_usbpd_notify.c @@ -64,7 +64,7 @@ static void cros_usbpd_get_event_and_notify(struct device *dev, /* * We still send a 0 event out to older devices which don't - * have the updated device heirarchy. + * have the updated device hierarchy. */ if (!ec_dev) { dev_dbg(dev, @@ -115,7 +115,7 @@ static int cros_usbpd_notify_probe_acpi(struct platform_device *pdev) if (!ec_dev) { /* * We continue even for older devices which don't have the - * correct device heirarchy, namely, GOOG0003 is a child + * correct device hierarchy, namely, GOOG0003 is a child * of GOOG0004. If GOOG0003 is a child of GOOG0004 and we * can't get a pointer to the Chrome EC device, defer the * probe function. diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h index 749d985e9da2..a7bd69d83522 100644 --- a/include/linux/platform_data/cros_ec_commands.h +++ b/include/linux/platform_data/cros_ec_commands.h @@ -1344,6 +1344,26 @@ enum ec_feature_code { * The EC supports UCSI PPM. */ EC_FEATURE_UCSI_PPM = 54, + /* + * The EC supports Strauss keyboard. + */ + EC_FEATURE_STRAUSS = 55, + /* + * The EC supports PoE. + */ + EC_FEATURE_POE = 56, + /* + * The EC supports a hybrid boost charger + */ + EC_FEATURE_CHARGER_HYBRID_POWER_BOOST = 57, + /* + * Support signaling new console logs via host event + */ + EC_FEATURE_CONSOLE_LOG_EVENT = 58, + /* + * The EC supports power monitoring + */ + EC_FEATURE_PWRMON = 59, }; #define EC_FEATURE_MASK_0(event_code) BIT(event_code % 32) @@ -3516,6 +3536,9 @@ enum ec_mkbp_event { /* Peripheral device charger event */ EC_MKBP_EVENT_PCHG = 12, + /* Power monitor telemetry event */ + EC_MKBP_EVENT_PWRMON = 13, + /* Number of MKBP events */ EC_MKBP_EVENT_COUNT, }; @@ -3599,6 +3622,12 @@ union __ec_align_offset1 ec_response_get_next_data_v3 { uint32_t cec_events; uint8_t cec_message[16]; + + struct __ec_todo_packed { + int64_t value; + uint32_t samples; + uint8_t channel_id; + } pwrmon_data; }; BUILD_ASSERT(sizeof(union ec_response_get_next_data_v3) == 18); @@ -6589,6 +6618,49 @@ struct ec_params_usb_pd_mux_ack { uint8_t port; /* USB-C port number */ } __ec_align1; +/** + * Power monitoring. Used to read power consumptions on rails + */ +#define EC_CMD_PWRMON 0x0608 + +enum ec_pwrmon_cmd { + EC_PWRMON_GET_CHANNEL_COUNT = 0, + EC_PWRMON_DUMP_INFO = 1, + EC_PWRMON_SET_RATE = 2, + EC_PWRMON_GET_RATE = 3, + EC_PWRMON_START = 4, + EC_PWRMON_STOP = 5, + EC_PWRMON_LATCH = 6, +}; + +struct ec_params_pwrmon { + uint8_t cmd; + union { + uint16_t set_rate; + uint8_t channel_id; + } __ec_align2; + + /* + * The following commands have no args: + * + * start, stop, latch + * + */ +} __ec_align4; + +struct pwrmon_dump_info { + uint8_t channel_id; + char channel_name[32]; +} __ec_align4; + +struct ec_response_pwrmon { + union { + uint16_t sample_rate; + uint8_t channel_count; + struct pwrmon_dump_info dump_info; + } __ec_align4; +} __ec_align4; + /*****************************************************************************/ /* * Reserve a range of host commands for board-specific, experimental, or |
