1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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");
}
}
|