mirror of
https://git.savannah.gnu.org/git/grub.git
synced 2026-10-23 07:39:22 +00:00
always use older cros protocol. We don't realy need new one
This commit is contained in:
1 parent
40562ddf1e
commit
03104c2d98
3 files changed
+4
-673
No files matched your search
@@ -49,7 +49,8 @@ grub_cros_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused))
|
||||
{
|
||||
struct cros_ec_keyscan scan;
|
||||
int i, j;
|
||||
cros_ec_scan_keyboard(&scan);
|
||||
if (cros_ec_scan_keyboard(&scan) < 0)
|
||||
return GRUB_TERM_NO_KEY;
|
||||
for (i = 0; i < CROS_EC_KEYSCAN_COLS; i++)
|
||||
if (scan.data[i] ^ old_scan.data[i])
|
||||
for (j = 0; j < CROS_EC_KEYSCAN_ROWS; j++)
|
||||
@@ -98,7 +99,6 @@ cros_attach(const struct grub_fdtbus_dev *dev __attribute__ ((unused)))
|
||||
|
||||
ps2_state.current_set = 1;
|
||||
ps2_state.at_keyboard_status = 0;
|
||||
cros_ec_init();
|
||||
grub_term_register_input ("cros_keyboard", &grub_cros_keyboard_term);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
@@ -100,21 +100,6 @@ spi_stop (void)
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
|
||||
typedef int (*SendCommandFunc)(int cmd, int cmd_version, const void *dout,
|
||||
int dout_len, void *dinp, int din_len);
|
||||
|
||||
SendCommandFunc send_command_func;
|
||||
|
||||
static struct ec_host_request *proto3_request;
|
||||
static int proto3_request_size;
|
||||
|
||||
static struct ec_host_response *proto3_response;
|
||||
static int proto3_response_size;
|
||||
|
||||
static int max_param_size;
|
||||
static int passthru_param_size;
|
||||
static int initialized;
|
||||
|
||||
static const uint64_t FramingTimeoutUs = 1000 * 1000;
|
||||
|
||||
static const uint8_t EcFramingByte = 0xec;
|
||||
@@ -244,311 +229,9 @@ enum ec_status {
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Value written to legacy command port / prefix byte to indicate protocol
|
||||
* 3+ structs are being used. Usage is bus-dependent.
|
||||
*/
|
||||
#define EC_COMMAND_PROTOCOL_3 0xda
|
||||
|
||||
#define EC_HOST_REQUEST_VERSION 3
|
||||
|
||||
/* Version 3 request from host */
|
||||
struct ec_host_request {
|
||||
/* Struct version (=3)
|
||||
*
|
||||
* EC will return EC_RES_INVALID_HEADER if it receives a header with a
|
||||
* version it doesn't know how to parse.
|
||||
*/
|
||||
uint8_t struct_version;
|
||||
|
||||
/*
|
||||
* Checksum of request and data; sum of all bytes including checksum
|
||||
* should total to 0.
|
||||
*/
|
||||
uint8_t checksum;
|
||||
|
||||
/* Command code */
|
||||
uint16_t command;
|
||||
|
||||
/* Command version */
|
||||
uint8_t command_version;
|
||||
|
||||
/* Unused byte in current protocol version; set to 0 */
|
||||
uint8_t reserved;
|
||||
|
||||
/* Length of data which follows this header */
|
||||
uint16_t data_len;
|
||||
} __packed;
|
||||
|
||||
#define EC_HOST_RESPONSE_VERSION 3
|
||||
|
||||
/* Version 3 response from EC */
|
||||
struct ec_host_response {
|
||||
/* Struct version (=3) */
|
||||
uint8_t struct_version;
|
||||
|
||||
/*
|
||||
* Checksum of response and data; sum of all bytes including checksum
|
||||
* should total to 0.
|
||||
*/
|
||||
uint8_t checksum;
|
||||
|
||||
/* Result code (EC_RES_*) */
|
||||
uint16_t result;
|
||||
|
||||
/* Length of data which follows this header */
|
||||
uint16_t data_len;
|
||||
|
||||
/* Unused bytes in current protocol version; set to 0 */
|
||||
uint16_t reserved;
|
||||
} __packed;
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Notes on commands:
|
||||
*
|
||||
* Each command is an 16-bit command value. Commands which take params or
|
||||
* return response data specify structs for that data. If no struct is
|
||||
* specified, the command does not input or output data, respectively.
|
||||
* Parameter/response length is implicit in the structs. Some underlying
|
||||
* communication protocols (I2C, SPI) may add length or checksum headers, but
|
||||
* those are implementation-dependent and not defined here.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
/* General / test commands */
|
||||
|
||||
/*
|
||||
* Get protocol version, used to deal with non-backward compatible protocol
|
||||
* changes.
|
||||
*/
|
||||
#define EC_CMD_PROTO_VERSION 0x00
|
||||
|
||||
struct ec_response_proto_version {
|
||||
uint32_t version;
|
||||
} __packed;
|
||||
|
||||
|
||||
/*
|
||||
* Check EC communcations status (busy). This is needed on i2c/spi but not
|
||||
* on lpc since it has its own out-of-band busy indicator.
|
||||
*
|
||||
* lpc must read the status from the command register. Attempting this on
|
||||
* lpc will overwrite the args/parameter space and corrupt its data.
|
||||
*/
|
||||
#define EC_CMD_GET_COMMS_STATUS 0x09
|
||||
|
||||
/* Avoid using ec_status which is for return values */
|
||||
enum ec_comms_status {
|
||||
EC_COMMS_STATUS_PROCESSING = 1 << 0, /* Processing cmd */
|
||||
};
|
||||
|
||||
struct ec_response_get_comms_status {
|
||||
uint32_t flags; /* Mask of enum ec_comms_status */
|
||||
} __packed;
|
||||
|
||||
/* Get prococol information */
|
||||
#define EC_CMD_GET_PROTOCOL_INFO 0x0b
|
||||
|
||||
/* Flags for ec_response_get_protocol_info.flags */
|
||||
/* EC_RES_IN_PROGRESS may be returned if a command is slow */
|
||||
#define EC_PROTOCOL_INFO_IN_PROGRESS_SUPPORTED (1 << 0)
|
||||
|
||||
struct ec_response_get_protocol_info {
|
||||
/* Fields which exist if at least protocol version 3 supported */
|
||||
|
||||
/* Bitmask of protocol versions supported (1 << n means version n)*/
|
||||
uint32_t protocol_versions;
|
||||
|
||||
/* Maximum request packet size, in bytes */
|
||||
uint16_t max_request_packet_size;
|
||||
|
||||
/* Maximum response packet size, in bytes */
|
||||
uint16_t max_response_packet_size;
|
||||
|
||||
/* Flags; see EC_PROTOCOL_INFO_* */
|
||||
uint32_t flags;
|
||||
} __packed;
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Real-time clock */
|
||||
|
||||
/* RTC params and response structures */
|
||||
struct ec_params_rtc {
|
||||
uint32_t time;
|
||||
} __packed;
|
||||
|
||||
struct ec_response_rtc {
|
||||
uint32_t time;
|
||||
} __packed;
|
||||
|
||||
/* These use ec_response_rtc */
|
||||
#define EC_CMD_RTC_GET_VALUE 0x44
|
||||
#define EC_CMD_RTC_GET_ALARM 0x45
|
||||
|
||||
/* These all use ec_params_rtc */
|
||||
#define EC_CMD_RTC_SET_VALUE 0x46
|
||||
#define EC_CMD_RTC_SET_ALARM 0x47
|
||||
|
||||
/*****************************************************************************/
|
||||
/* MKBP - Matrix KeyBoard Protocol */
|
||||
|
||||
/*
|
||||
* Read key state
|
||||
*
|
||||
* Returns raw data for keyboard cols; see ec_response_mkbp_info.cols for
|
||||
* expected response size.
|
||||
*/
|
||||
#define EC_CMD_MKBP_STATE 0x60
|
||||
|
||||
|
||||
/* Simulate key press */
|
||||
#define EC_CMD_MKBP_SIMULATE_KEY 0x62
|
||||
|
||||
struct ec_params_mkbp_simulate_key {
|
||||
uint8_t col;
|
||||
uint8_t row;
|
||||
uint8_t pressed;
|
||||
} __packed;
|
||||
|
||||
/* Configure keyboard scanning */
|
||||
#define EC_CMD_MKBP_SET_CONFIG 0x64
|
||||
#define EC_CMD_MKBP_GET_CONFIG 0x65
|
||||
|
||||
/* flags */
|
||||
enum mkbp_config_flags {
|
||||
EC_MKBP_FLAGS_ENABLE = 1, /* Enable keyboard scanning */
|
||||
};
|
||||
|
||||
enum mkbp_config_valid {
|
||||
EC_MKBP_VALID_SCAN_PERIOD = 1 << 0,
|
||||
EC_MKBP_VALID_POLL_TIMEOUT = 1 << 1,
|
||||
EC_MKBP_VALID_MIN_POST_SCAN_DELAY = 1 << 3,
|
||||
EC_MKBP_VALID_OUTPUT_SETTLE = 1 << 4,
|
||||
EC_MKBP_VALID_DEBOUNCE_DOWN = 1 << 5,
|
||||
EC_MKBP_VALID_DEBOUNCE_UP = 1 << 6,
|
||||
EC_MKBP_VALID_FIFO_MAX_DEPTH = 1 << 7,
|
||||
};
|
||||
|
||||
/* Configuration for our key scanning algorithm */
|
||||
struct ec_mkbp_config {
|
||||
uint32_t valid_mask; /* valid fields */
|
||||
uint8_t flags; /* some flags (enum mkbp_config_flags) */
|
||||
uint8_t valid_flags; /* which flags are valid */
|
||||
uint16_t scan_period_us; /* period between start of scans */
|
||||
/* revert to interrupt mode after no activity for this long */
|
||||
uint32_t poll_timeout_us;
|
||||
/*
|
||||
* minimum post-scan relax time. Once we finish a scan we check
|
||||
* the time until we are due to start the next one. If this time is
|
||||
* shorter this field, we use this instead.
|
||||
*/
|
||||
uint16_t min_post_scan_delay_us;
|
||||
/* delay between setting up output and waiting for it to settle */
|
||||
uint16_t output_settle_us;
|
||||
uint16_t debounce_down_us; /* time for debounce on key down */
|
||||
uint16_t debounce_up_us; /* time for debounce on key up */
|
||||
/* maximum depth to allow for fifo (0 = no keyscan output) */
|
||||
uint8_t fifo_max_depth;
|
||||
} __packed;
|
||||
|
||||
struct ec_params_mkbp_set_config {
|
||||
struct ec_mkbp_config config;
|
||||
} __packed;
|
||||
|
||||
struct ec_response_mkbp_get_config {
|
||||
struct ec_mkbp_config config;
|
||||
} __packed;
|
||||
|
||||
/* Run the key scan emulation */
|
||||
#define EC_CMD_KEYSCAN_SEQ_CTRL 0x66
|
||||
|
||||
enum ec_keyscan_seq_cmd {
|
||||
EC_KEYSCAN_SEQ_STATUS = 0, /* Get status information */
|
||||
EC_KEYSCAN_SEQ_CLEAR = 1, /* Clear sequence */
|
||||
EC_KEYSCAN_SEQ_ADD = 2, /* Add item to sequence */
|
||||
EC_KEYSCAN_SEQ_START = 3, /* Start running sequence */
|
||||
EC_KEYSCAN_SEQ_COLLECT = 4, /* Collect sequence summary data */
|
||||
};
|
||||
|
||||
enum ec_collect_flags {
|
||||
/*
|
||||
* Indicates this scan was processed by the EC. Due to timing, some
|
||||
* scans may be skipped.
|
||||
*/
|
||||
EC_KEYSCAN_SEQ_FLAG_DONE = 1 << 0,
|
||||
};
|
||||
|
||||
struct ec_collect_item {
|
||||
uint8_t flags; /* some flags (enum ec_collect_flags) */
|
||||
};
|
||||
|
||||
struct ec_params_keyscan_seq_ctrl {
|
||||
uint8_t cmd; /* Command to send (enum ec_keyscan_seq_cmd) */
|
||||
union {
|
||||
struct {
|
||||
uint8_t active; /* still active */
|
||||
uint8_t num_items; /* number of items */
|
||||
/* Current item being presented */
|
||||
uint8_t cur_item;
|
||||
} status;
|
||||
struct {
|
||||
/*
|
||||
* Absolute time for this scan, measured from the
|
||||
* start of the sequence.
|
||||
*/
|
||||
uint32_t time_us;
|
||||
uint8_t scan[0]; /* keyscan data */
|
||||
} add;
|
||||
struct {
|
||||
uint8_t start_item; /* First item to return */
|
||||
uint8_t num_items; /* Number of items to return */
|
||||
} collect;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct ec_result_keyscan_seq_ctrl {
|
||||
union {
|
||||
struct {
|
||||
uint8_t num_items; /* Number of items */
|
||||
/* Data for each item */
|
||||
struct ec_collect_item item[0];
|
||||
} collect;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Get the next pending MKBP event.
|
||||
*
|
||||
* Returns EC_RES_UNAVAILABLE if there is no event pending.
|
||||
*/
|
||||
#define EC_CMD_GET_NEXT_EVENT 0x67
|
||||
|
||||
enum ec_mkbp_event {
|
||||
/* Keyboard matrix changed. The event data is the new matrix state. */
|
||||
EC_MKBP_EVENT_KEY_MATRIX = 0,
|
||||
|
||||
/* New host event. The event data is 4 bytes of host event flags. */
|
||||
EC_MKBP_EVENT_HOST_EVENT = 1,
|
||||
|
||||
/* New Sensor FIFO data. The event data is fifo_info structure. */
|
||||
EC_MKBP_EVENT_SENSOR_FIFO = 2,
|
||||
|
||||
/* Number of MKBP events */
|
||||
EC_MKBP_EVENT_COUNT,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Resend last response (not supported on LPC).
|
||||
*
|
||||
* Returns EC_RES_UNAVAILABLE if there is no response available - for example,
|
||||
* there was no previous command, or the previous command's response was too
|
||||
* big to save.
|
||||
*/
|
||||
#define EC_CMD_RESEND_RESPONSE 0xdb
|
||||
|
||||
/*
|
||||
* This header byte on a command indicate version 0. Any header byte less
|
||||
* than this means that we are talking to an old EC which doesn't support
|
||||
@@ -619,39 +302,6 @@ enum {
|
||||
CROS_EC_SPI_OUT_HDR_SIZE = 3
|
||||
};
|
||||
|
||||
static int send_packet(const void *dout, uint32_t dout_len,
|
||||
void *din, uint32_t din_len)
|
||||
{
|
||||
while (grub_get_time_us() - last_transfer < 200)
|
||||
;
|
||||
|
||||
if (spi_start())
|
||||
return -1;
|
||||
|
||||
// Allow EC to ramp up clock after being awaken.
|
||||
// See chrome-os-partner:32223 for more details.
|
||||
grub_microsleep (100);
|
||||
|
||||
if (spi_send (dout, dout_len)) {
|
||||
stop_bus();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Wait until the EC is ready.
|
||||
if (wait_for_frame()) {
|
||||
stop_bus();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (spi_read(din, din_len)) {
|
||||
stop_bus();
|
||||
return -1;
|
||||
}
|
||||
|
||||
stop_bus();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_uint8_t busbuf[256];
|
||||
#define MSG_BYTES sizeof (busbuf)
|
||||
|
||||
@@ -767,215 +417,6 @@ static int send_command(uint8_t cmd, int cmd_version,
|
||||
/* Timeout waiting for a flash erase command to complete */
|
||||
static const int CROS_EC_CMD_TIMEOUT_MS = 5000;
|
||||
|
||||
static void cros_ec_dump_data(const char *name, int cmd, const void *data, int len)
|
||||
{
|
||||
(void) name;
|
||||
(void) cmd;
|
||||
(void) data;
|
||||
(void) len;
|
||||
#ifdef DEBUG
|
||||
const uint8_t *bytes = data;
|
||||
int i;
|
||||
|
||||
printf("%s: ", name);
|
||||
if (cmd != -1)
|
||||
printf("cmd=%#x: ", cmd);
|
||||
for (i = 0; i < len; i++)
|
||||
printf("%02x ", bytes[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a request packet for protocol version 3.
|
||||
*
|
||||
* @param rq Request structure to fill
|
||||
* @param rq_size Size of request structure, including data
|
||||
* @param cmd Command to send (EC_CMD_...)
|
||||
* @param cmd_version Version of command to send (EC_VER_...)
|
||||
* @param dout Output data (may be NULL If dout_len=0)
|
||||
* @param dout_len Size of output data in bytes
|
||||
* @return packet size in bytes, or <0 if error.
|
||||
*/
|
||||
static int create_proto3_request(struct ec_host_request *rq, int rq_size,
|
||||
int cmd, int cmd_version,
|
||||
const void *dout, int dout_len)
|
||||
{
|
||||
int out_bytes = dout_len + sizeof(*rq);
|
||||
|
||||
/* Fail if output size is too big */
|
||||
if (out_bytes > rq_size) {
|
||||
printf("%s: Cannot send %d bytes\n", __func__, dout_len);
|
||||
return -EC_RES_REQUEST_TRUNCATED;
|
||||
}
|
||||
|
||||
/* Fill in request packet */
|
||||
rq->struct_version = EC_HOST_REQUEST_VERSION;
|
||||
rq->checksum = 0;
|
||||
rq->command = cmd;
|
||||
rq->command_version = cmd_version;
|
||||
rq->reserved = 0;
|
||||
rq->data_len = dout_len;
|
||||
|
||||
/* Copy data after header */
|
||||
memcpy(rq + 1, dout, dout_len);
|
||||
|
||||
/* Write checksum field so the entire packet sums to 0 */
|
||||
rq->checksum = (uint8_t)(-cros_ec_calc_checksum(rq, out_bytes));
|
||||
|
||||
cros_ec_dump_data("out", cmd, rq, out_bytes);
|
||||
|
||||
/* Return size of request packet */
|
||||
return out_bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the device to receive a protocol version 3 response.
|
||||
*
|
||||
* @param rs_size Maximum size of response in bytes
|
||||
* @param din_len Maximum amount of data in the response
|
||||
* @return maximum expected number of bytes in response, or <0 if error.
|
||||
*/
|
||||
static int prepare_proto3_response_buffer(int rs_size, int din_len)
|
||||
{
|
||||
int in_bytes = din_len + sizeof(struct ec_host_response);
|
||||
|
||||
/* Fail if input size is too big */
|
||||
if (in_bytes > rs_size) {
|
||||
printf("%s: Cannot receive %d bytes\n", __func__, din_len);
|
||||
return -EC_RES_RESPONSE_TOO_BIG;
|
||||
}
|
||||
|
||||
/* Return expected size of response packet */
|
||||
return in_bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a protocol version 3 response packet.
|
||||
*
|
||||
* @param resp Response structure to parse
|
||||
* @param dinp Returns pointer to response data
|
||||
* @param din_len Maximum size of data in response in bytes
|
||||
* @return number of bytes of response data, or <0 if error
|
||||
*/
|
||||
static int handle_proto3_response(struct ec_host_response *rs,
|
||||
uint8_t **dinp, int din_len)
|
||||
{
|
||||
int in_bytes;
|
||||
int csum;
|
||||
|
||||
cros_ec_dump_data("in-header", -1, rs, sizeof(*rs));
|
||||
|
||||
/* Check input data */
|
||||
if (rs->struct_version != EC_HOST_RESPONSE_VERSION) {
|
||||
printf("%s: EC response version mismatch\n", __func__);
|
||||
return -EC_RES_INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
if (rs->reserved) {
|
||||
printf("%s: EC response reserved != 0\n", __func__);
|
||||
return -EC_RES_INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
if (rs->data_len > din_len) {
|
||||
printf("%s: EC returned too much data\n", __func__);
|
||||
return -EC_RES_RESPONSE_TOO_BIG;
|
||||
}
|
||||
|
||||
cros_ec_dump_data("in-data", -1, rs + sizeof(*rs), rs->data_len);
|
||||
|
||||
/* Update in_bytes to actual data size */
|
||||
in_bytes = sizeof(*rs) + rs->data_len;
|
||||
|
||||
/* Verify checksum */
|
||||
csum = cros_ec_calc_checksum(rs, in_bytes);
|
||||
if (csum) {
|
||||
printf("%s: EC response checksum invalid: 0x%02x\n", __func__,
|
||||
csum);
|
||||
return -EC_RES_INVALID_CHECKSUM;
|
||||
}
|
||||
|
||||
/* Return error result, if any */
|
||||
if (rs->result)
|
||||
return -(int)rs->result;
|
||||
|
||||
/* If the caller wants the response data, copy it out */
|
||||
if (dinp)
|
||||
memcpy(dinp, rs + 1, din_len);
|
||||
|
||||
return rs->data_len;
|
||||
}
|
||||
|
||||
static int send_command_proto3_work(int cmd, int cmd_version,
|
||||
const void *dout, int dout_len,
|
||||
void *dinp, int din_len)
|
||||
{
|
||||
int out_bytes, in_bytes;
|
||||
int rv;
|
||||
|
||||
/* Create request packet */
|
||||
out_bytes = create_proto3_request(proto3_request, proto3_request_size,
|
||||
cmd, cmd_version, dout, dout_len);
|
||||
if (out_bytes < 0)
|
||||
return out_bytes;
|
||||
|
||||
/* Prepare response buffer */
|
||||
in_bytes = prepare_proto3_response_buffer(proto3_response_size,
|
||||
din_len);
|
||||
|
||||
if (in_bytes < 0)
|
||||
return in_bytes;
|
||||
|
||||
rv = send_packet(proto3_request, out_bytes,
|
||||
proto3_response, in_bytes);
|
||||
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
/* Process the response */
|
||||
return handle_proto3_response(proto3_response, dinp, din_len);
|
||||
}
|
||||
|
||||
static int send_command_proto3(int cmd, int cmd_version,
|
||||
const void *dout, int dout_len,
|
||||
void *dinp, int din_len)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = send_command_proto3_work(cmd, cmd_version, dout, dout_len,
|
||||
dinp, din_len);
|
||||
|
||||
/* If the command doesn't complete, wait a while */
|
||||
if (rv == -EC_RES_IN_PROGRESS) {
|
||||
struct ec_response_get_comms_status resp;
|
||||
uint64_t start;
|
||||
|
||||
/* Wait for command to complete */
|
||||
start = grub_get_time_ms();
|
||||
do {
|
||||
int ret;
|
||||
|
||||
mdelay(50); /* Insert some reasonable delay */
|
||||
ret = send_command_proto3_work(EC_CMD_GET_COMMS_STATUS,
|
||||
0, NULL, 0, &resp, sizeof(resp));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (grub_get_time_ms() - start > CROS_EC_CMD_TIMEOUT_MS) {
|
||||
printf("%s: Command %#02x timeout",
|
||||
__func__, cmd);
|
||||
return -EC_RES_TIMEOUT;
|
||||
}
|
||||
} while (resp.flags & EC_COMMS_STATUS_PROCESSING);
|
||||
|
||||
/* OK it completed, so read the status response */
|
||||
rv = send_command_proto3_work(EC_CMD_RESEND_RESPONSE,
|
||||
0, NULL, 0, dinp, din_len);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a command to the ChromeOS EC device and optionally return the reply.
|
||||
*
|
||||
@@ -1002,36 +443,6 @@ static int send_command_proto2(int cmd, int cmd_version,
|
||||
len = send_command(cmd, cmd_version, dout,
|
||||
dout_len, din, din_len);
|
||||
|
||||
/* If the command doesn't complete, wait a while */
|
||||
if (len == -EC_RES_IN_PROGRESS) {
|
||||
struct ec_response_get_comms_status resp;
|
||||
uint64_t start;
|
||||
|
||||
/* Wait for command to complete */
|
||||
start = grub_get_time_ms();
|
||||
do {
|
||||
int ret;
|
||||
|
||||
mdelay(50); /* Insert some reasonable delay */
|
||||
ret = send_command(
|
||||
EC_CMD_GET_COMMS_STATUS,
|
||||
0, NULL, 0, &resp, sizeof(resp));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (grub_get_time_ms() - start > CROS_EC_CMD_TIMEOUT_MS) {
|
||||
printf("%s: Command %#02x timeout",
|
||||
__func__, cmd);
|
||||
return -EC_RES_TIMEOUT;
|
||||
}
|
||||
} while (resp.flags & EC_COMMS_STATUS_PROCESSING);
|
||||
|
||||
/* OK it completed, so read the status response */
|
||||
len = send_command(
|
||||
EC_CMD_RESEND_RESPONSE,
|
||||
0, NULL, 0, din, din_len);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("%s: len=%d, din=%p\n", __func__, len, din);
|
||||
#endif
|
||||
@@ -1043,20 +454,8 @@ static int ec_command(int cmd, int cmd_version,
|
||||
const void *dout, int dout_len,
|
||||
void *din, int din_len)
|
||||
{
|
||||
if (!initialized && cros_ec_init())
|
||||
return -1;
|
||||
|
||||
return send_command_func(cmd, cmd_version, dout, dout_len,
|
||||
din, din_len);
|
||||
}
|
||||
|
||||
static int cros_ec_get_protocol_info(struct ec_response_get_protocol_info *info)
|
||||
{
|
||||
if (ec_command(EC_CMD_GET_PROTOCOL_INFO, 0, NULL, 0, info,
|
||||
sizeof(*info)) < (int)sizeof(*info))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
return send_command_proto2(cmd, cmd_version, dout, dout_len,
|
||||
din, din_len);
|
||||
}
|
||||
|
||||
int cros_ec_scan_keyboard(struct cros_ec_keyscan *scan)
|
||||
@@ -1067,69 +466,3 @@ int cros_ec_scan_keyboard(struct cros_ec_keyscan *scan)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_max_proto3_sizes(int request_size, int response_size,
|
||||
int passthru_size)
|
||||
{
|
||||
grub_free(proto3_request);
|
||||
grub_free(proto3_response);
|
||||
|
||||
if (request_size)
|
||||
proto3_request = grub_malloc(request_size);
|
||||
else
|
||||
proto3_request = NULL;
|
||||
if (response_size)
|
||||
proto3_response = grub_malloc(response_size);
|
||||
else
|
||||
proto3_response = NULL;
|
||||
|
||||
proto3_request_size = request_size;
|
||||
proto3_response_size = response_size;
|
||||
|
||||
max_param_size = proto3_request_size - sizeof(struct ec_host_request);
|
||||
|
||||
passthru_param_size = passthru_size - sizeof(struct ec_host_request);
|
||||
if (passthru_param_size > max_param_size)
|
||||
passthru_param_size = max_param_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cros_ec_init(void)
|
||||
{
|
||||
if (initialized)
|
||||
return 0;
|
||||
|
||||
initialized = 1;
|
||||
|
||||
// Figure out what protocol version to use.
|
||||
|
||||
send_command_func = &send_command_proto3;
|
||||
if (set_max_proto3_sizes(DEFAULT_BUF_SIZE, DEFAULT_BUF_SIZE,
|
||||
DEFAULT_BUF_SIZE))
|
||||
return -1;
|
||||
|
||||
struct ec_response_get_protocol_info info;
|
||||
if (cros_ec_get_protocol_info(&info)) {
|
||||
set_max_proto3_sizes(0, 0, 0);
|
||||
send_command_func = NULL;
|
||||
} else {
|
||||
printf("%s: CrosEC protocol v3 supported (%d, %d)\n",
|
||||
__func__,
|
||||
info.max_request_packet_size,
|
||||
info.max_response_packet_size);
|
||||
|
||||
set_max_proto3_sizes(info.max_request_packet_size,
|
||||
info.max_response_packet_size,
|
||||
0);
|
||||
}
|
||||
|
||||
if (!send_command_func) {
|
||||
// Fall back to protocol version 2.
|
||||
send_command_func = &send_command_proto2;
|
||||
max_param_size = EC_PROTO2_MAX_PARAM_SIZE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -54,6 +54,4 @@ typedef struct CrosEcBusOps
|
||||
void (*write)(const grub_uint8_t *data, grub_uint16_t port, int size);
|
||||
} CrosEcBusOps;
|
||||
|
||||
int cros_ec_set_bus(CrosEcBusOps *bus);
|
||||
int cros_ec_scan_keyboard(struct cros_ec_keyscan *scan);
|
||||
int cros_ec_init(void);
|
||||
Reference in new issue
Block a user