diff options
Diffstat (limited to 'chip/mt8192_scp/hostcmd.c')
-rw-r--r-- | chip/mt8192_scp/hostcmd.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/chip/mt8192_scp/hostcmd.c b/chip/mt8192_scp/hostcmd.c new file mode 100644 index 0000000000..42a463ee56 --- /dev/null +++ b/chip/mt8192_scp/hostcmd.c @@ -0,0 +1,128 @@ +/* Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "console.h" +#include "host_command.h" +#include "ipi_chip.h" +#include "util.h" + +#define CPRINTF(format, args...) cprintf(CC_IPI, format, ##args) +#define CPRINTS(format, args...) cprints(CC_IPI, format, ##args) + +#define HOSTCMD_MAX_REQUEST_SIZE CONFIG_IPC_SHARED_OBJ_BUF_SIZE +/* Reserve 1 extra byte for HOSTCMD_TYPE and 3 bytes for padding. */ +#define HOSTCMD_MAX_RESPONSE_SIZE (CONFIG_IPC_SHARED_OBJ_BUF_SIZE - 4) +#define HOSTCMD_TYPE_HOSTCMD 1 +#define HOSTCMD_TYPE_HOSTEVENT 2 + +/* + * hostcmd and hostevent share the same IPI ID, and use first byte type to + * indicate its type. + */ +static struct hostcmd_data { + const uint8_t type; + /* To be compatible with CONFIG_HOSTCMD_ALIGNED */ + uint8_t response[HOSTCMD_MAX_RESPONSE_SIZE] __aligned(4); +} hc_cmd_obj = { .type = HOSTCMD_TYPE_HOSTCMD }; +BUILD_ASSERT(sizeof(struct hostcmd_data) == CONFIG_IPC_SHARED_OBJ_BUF_SIZE); + +/* Size of the rpmsg device name, should sync across kernel and EC. */ +#define RPMSG_NAME_SIZE 32 + +/* + * The layout of name service message. + * This should sync across kernel and EC. + */ +struct rpmsg_ns_msg { + /* Name of the corresponding rpmsg_driver. */ + char name[RPMSG_NAME_SIZE]; + /* IPC ID */ + uint32_t addr; +}; + +static void hostcmd_send_response_packet(struct host_packet *pkt) +{ + int ret; + + ret = ipi_send(SCP_IPI_HOST_COMMAND, &hc_cmd_obj, + pkt->response_size + + offsetof(struct hostcmd_data, response), + 1); + if (ret) + CPRINTS("failed to %s(), ret=%d", __func__, ret); +} + +static void hostcmd_handler(int32_t id, void *buf, uint32_t len) +{ + static struct host_packet packet; + uint8_t *in_msg = buf; + struct ec_host_request *r = (struct ec_host_request *)in_msg; + int i; + + if (in_msg[0] != EC_HOST_REQUEST_VERSION) { + CPRINTS("ERROR: Protocol V2 is not supported!"); + CPRINTF("in_msg=["); + for (i = 0; i < len; i++) + CPRINTF("%02x ", in_msg[i]); + CPRINTF("]\n"); + return; + } + + /* Protocol version 3 */ + + packet.send_response = hostcmd_send_response_packet; + + /* + * Just assign the buffer to request, host_packet_receive + * handles the buffer copy. + */ + packet.request = (void *)r; + packet.request_temp = NULL; + packet.request_max = HOSTCMD_MAX_REQUEST_SIZE; + packet.request_size = host_request_expected_size(r); + + packet.response = hc_cmd_obj.response; + /* Reserve space for the preamble and trailing byte */ + packet.response_max = HOSTCMD_MAX_RESPONSE_SIZE; + packet.response_size = 0; + + packet.driver_result = EC_RES_SUCCESS; + + host_packet_receive(&packet); +} +DECLARE_IPI(SCP_IPI_HOST_COMMAND, hostcmd_handler, 0); + +/* + * Get protocol information + */ +static enum ec_status hostcmd_get_protocol_info(struct host_cmd_handler_args *args) +{ + struct ec_response_get_protocol_info *r = args->response; + + memset(r, 0, sizeof(*r)); + r->protocol_versions |= BIT(3); + r->max_request_packet_size = HOSTCMD_MAX_REQUEST_SIZE; + r->max_response_packet_size = HOSTCMD_MAX_RESPONSE_SIZE; + + args->response_size = sizeof(*r); + + return EC_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, hostcmd_get_protocol_info, + EC_VER_MASK(0)); + +void hostcmd_init(void) +{ + int ret; + struct rpmsg_ns_msg ns_msg; + + if (IS_ENABLED(CONFIG_RPMSG_NAME_SERVICE)) { + ns_msg.addr = SCP_IPI_HOST_COMMAND; + strncpy(ns_msg.name, "cros-ec-rpmsg", RPMSG_NAME_SIZE); + ret = ipi_send(SCP_IPI_NS_SERVICE, &ns_msg, sizeof(ns_msg), 1); + if (ret) + CPRINTS("Failed to announce host command channel"); + } +} |