ec_host_cmd: add eSPI peripheral for the host commands
This commit adds the support for host commands being transported by the eSPI subsystem. Signed-off-by: Michał Barnaś <mb@semihalf.com>
This commit is contained in:
parent
b91849c4bd
commit
94458f88b9
9 changed files with 157 additions and 5 deletions
|
@ -5,3 +5,7 @@ zephyr_library()
|
||||||
zephyr_library_sources_ifdef(
|
zephyr_library_sources_ifdef(
|
||||||
CONFIG_EC_HOST_CMD_SIMULATOR
|
CONFIG_EC_HOST_CMD_SIMULATOR
|
||||||
ec_host_cmd_simulator.c)
|
ec_host_cmd_simulator.c)
|
||||||
|
|
||||||
|
zephyr_library_sources_ifdef(
|
||||||
|
CONFIG_EC_HOST_CMD_PERIPH_ESPI
|
||||||
|
ec_host_cmd_periph_espi.c)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
menuconfig EC_HOST_CMD_PERIPH
|
menuconfig EC_HOST_CMD_PERIPH
|
||||||
bool "Embedded Controller Host Command peripheral support"
|
bool "Embedded Controller Host Command peripheral support"
|
||||||
|
depends on EC_HOST_CMD
|
||||||
help
|
help
|
||||||
Enable the embedded controller host command peripheral driver. This
|
Enable the embedded controller host command peripheral driver. This
|
||||||
is needed by the EC host command framework to send and receive data
|
is needed by the EC host command framework to send and receive data
|
||||||
|
@ -12,11 +13,24 @@ menuconfig EC_HOST_CMD_PERIPH
|
||||||
|
|
||||||
if EC_HOST_CMD_PERIPH
|
if EC_HOST_CMD_PERIPH
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Host commands peripheral"
|
||||||
|
|
||||||
config EC_HOST_CMD_SIMULATOR
|
config EC_HOST_CMD_SIMULATOR
|
||||||
bool "Embedded Controller Host Command Peripheral Simulator"
|
bool "Embedded Controller Host Command Peripheral Simulator"
|
||||||
default y
|
|
||||||
depends on DT_HAS_ZEPHYR_SIM_EC_HOST_CMD_PERIPH_ENABLED
|
depends on DT_HAS_ZEPHYR_SIM_EC_HOST_CMD_PERIPH_ENABLED
|
||||||
help
|
help
|
||||||
Enable the EC host command simulator.
|
Enable the EC host command simulator.
|
||||||
|
|
||||||
|
config EC_HOST_CMD_PERIPH_ESPI
|
||||||
|
bool "Host commands support using eSPI bus"
|
||||||
|
depends on ESPI_PERIPHERAL_EC_HOST_CMD
|
||||||
|
depends on ESPI_PERIPHERAL_CUSTOM_OPCODE
|
||||||
|
depends on DT_HAS_ZEPHYR_EC_HOST_CMD_PERIPH_ESPI_ENABLED
|
||||||
|
help
|
||||||
|
Enable support for Embedded Controller host commands using
|
||||||
|
the eSPI bus.
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
endif # EC_HOST_CMD_PERIPH
|
endif # EC_HOST_CMD_PERIPH
|
||||||
|
|
106
drivers/ec_host_cmd_periph/ec_host_cmd_periph_espi.c
Normal file
106
drivers/ec_host_cmd_periph/ec_host_cmd_periph_espi.c
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 Google LLC
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT zephyr_ec_host_cmd_periph_espi
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/drivers/ec_host_cmd_periph/ec_host_cmd_periph.h>
|
||||||
|
#include <zephyr/drivers/espi.h>
|
||||||
|
#include <zephyr/mgmt/ec_host_cmd.h>
|
||||||
|
|
||||||
|
BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, "Invalid number of eSPI peripherals");
|
||||||
|
|
||||||
|
#define ESPI_BUS DT_PHANDLE(DT_DRV_INST(0), bus)
|
||||||
|
#define ESPI_DEVICE DEVICE_DT_GET(ESPI_BUS)
|
||||||
|
|
||||||
|
struct ec_host_cmd_periph_espi_data {
|
||||||
|
struct k_sem handler_owns;
|
||||||
|
struct k_sem dev_owns;
|
||||||
|
uint32_t rx_buffer_len;
|
||||||
|
struct espi_callback espi_cb;
|
||||||
|
uint8_t *espi_shm;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ec_host_cmd_periph_espi_handler(const struct device *dev, struct espi_callback *cb,
|
||||||
|
struct espi_event espi_evt)
|
||||||
|
{
|
||||||
|
struct ec_host_cmd_periph_espi_data *data =
|
||||||
|
CONTAINER_OF(cb, struct ec_host_cmd_periph_espi_data, espi_cb);
|
||||||
|
uint16_t event_type = (uint16_t)espi_evt.evt_details;
|
||||||
|
|
||||||
|
if (event_type != ESPI_PERIPHERAL_EC_HOST_CMD) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k_sem_take(&data->dev_owns, K_NO_WAIT) != 0) {
|
||||||
|
int res = EC_HOST_CMD_IN_PROGRESS;
|
||||||
|
|
||||||
|
espi_write_lpc_request(ESPI_DEVICE, ECUSTOM_HOST_CMD_SEND_RESULT, &res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_sem_give(&data->handler_owns);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ec_host_cmd_periph_espi_init(const struct device *dev, struct ec_host_cmd_periph_rx_ctx *rx_ctx)
|
||||||
|
{
|
||||||
|
struct ec_host_cmd_periph_espi_data *data = dev->data;
|
||||||
|
|
||||||
|
if (rx_ctx == NULL) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rx_ctx->buf = data->espi_shm;
|
||||||
|
rx_ctx->len = &data->rx_buffer_len;
|
||||||
|
rx_ctx->dev_owns = &data->dev_owns;
|
||||||
|
rx_ctx->handler_owns = &data->handler_owns;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ec_host_cmd_periph_espi_send(const struct device *dev,
|
||||||
|
const struct ec_host_cmd_periph_tx_buf *buf)
|
||||||
|
{
|
||||||
|
struct ec_host_cmd_periph_espi_data *data = dev->data;
|
||||||
|
struct ec_host_cmd_response_header *resp_hdr = buf->buf;
|
||||||
|
uint32_t result = resp_hdr->result;
|
||||||
|
|
||||||
|
memcpy(data->espi_shm, buf->buf, buf->len);
|
||||||
|
|
||||||
|
return espi_write_lpc_request(ESPI_DEVICE, ECUSTOM_HOST_CMD_SEND_RESULT, &result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct ec_host_cmd_periph_api ec_host_cmd_api = {
|
||||||
|
.init = &ec_host_cmd_periph_espi_init,
|
||||||
|
.send = &ec_host_cmd_periph_espi_send,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ec_host_cmd_espi_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
struct ec_host_cmd_periph_espi_data *data = dev->data;
|
||||||
|
|
||||||
|
/* Allow writing to rx buff at startup and block on reading. */
|
||||||
|
k_sem_init(&data->handler_owns, 0, 1);
|
||||||
|
k_sem_init(&data->dev_owns, 1, 1);
|
||||||
|
|
||||||
|
espi_init_callback(&data->espi_cb, ec_host_cmd_periph_espi_handler,
|
||||||
|
ESPI_BUS_PERIPHERAL_NOTIFICATION);
|
||||||
|
espi_add_callback(ESPI_DEVICE, &data->espi_cb);
|
||||||
|
|
||||||
|
espi_read_lpc_request(ESPI_DEVICE, ECUSTOM_HOST_CMD_GET_PARAM_MEMORY,
|
||||||
|
(uint32_t *)&data->espi_shm);
|
||||||
|
espi_read_lpc_request(ESPI_DEVICE, ECUSTOM_HOST_CMD_GET_PARAM_MEMORY_SIZE,
|
||||||
|
&data->rx_buffer_len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assume only one peripheral */
|
||||||
|
static struct ec_host_cmd_periph_espi_data espi_data;
|
||||||
|
DEVICE_DT_INST_DEFINE(0, ec_host_cmd_espi_init, NULL, &espi_data, NULL, POST_KERNEL,
|
||||||
|
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &ec_host_cmd_api);
|
|
@ -805,6 +805,9 @@ static int espi_it8xxx2_read_lpc_request(const struct device *dev,
|
||||||
*data = (uint32_t)&h2ram_pool[
|
*data = (uint32_t)&h2ram_pool[
|
||||||
CONFIG_ESPI_PERIPHERAL_HOST_CMD_PARAM_PORT_NUM];
|
CONFIG_ESPI_PERIPHERAL_HOST_CMD_PARAM_PORT_NUM];
|
||||||
break;
|
break;
|
||||||
|
case ECUSTOM_HOST_CMD_GET_PARAM_MEMORY_SIZE:
|
||||||
|
*data = CONFIG_ESPI_IT8XXX2_HC_H2RAM_SIZE;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -720,6 +720,9 @@ static int ecust_rd_req(const struct device *dev,
|
||||||
case ECUSTOM_HOST_CMD_GET_PARAM_MEMORY:
|
case ECUSTOM_HOST_CMD_GET_PARAM_MEMORY:
|
||||||
*data = (uint32_t)ec_host_cmd_sram;
|
*data = (uint32_t)ec_host_cmd_sram;
|
||||||
break;
|
break;
|
||||||
|
case ECUSTOM_HOST_CMD_GET_PARAM_MEMORY_SIZE:
|
||||||
|
*data = CONFIG_ESPI_XEC_PERIPHERAL_HOST_CMD_PARAM_SIZE;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -830,6 +830,9 @@ int npcx_host_periph_read_request(enum lpc_peripheral_opcode op,
|
||||||
case ECUSTOM_HOST_CMD_GET_PARAM_MEMORY:
|
case ECUSTOM_HOST_CMD_GET_PARAM_MEMORY:
|
||||||
*data = (uint32_t)shm_host_cmd;
|
*data = (uint32_t)shm_host_cmd;
|
||||||
break;
|
break;
|
||||||
|
case ECUSTOM_HOST_CMD_GET_PARAM_MEMORY_SIZE:
|
||||||
|
*data = CONFIG_ESPI_NPCX_PERIPHERAL_HOST_CMD_PARAM_SIZE;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
description: Host Command Peripheral using the eSPI bus
|
||||||
|
|
||||||
|
compatible: "zephyr,ec-host-cmd-periph-espi"
|
||||||
|
|
||||||
|
include: base.yaml
|
||||||
|
|
||||||
|
properties:
|
||||||
|
bus:
|
||||||
|
required: true
|
||||||
|
type: phandle
|
||||||
|
description:
|
||||||
|
Phandle to the eSPI bus which will be used for communication with AP
|
||||||
|
by the host commands subsystem
|
|
@ -285,6 +285,7 @@ enum lpc_peripheral_opcode {
|
||||||
/* Other customized transactions */
|
/* Other customized transactions */
|
||||||
ECUSTOM_HOST_SUBS_INTERRUPT_EN = ECUSTOM_START_OPCODE,
|
ECUSTOM_HOST_SUBS_INTERRUPT_EN = ECUSTOM_START_OPCODE,
|
||||||
ECUSTOM_HOST_CMD_GET_PARAM_MEMORY,
|
ECUSTOM_HOST_CMD_GET_PARAM_MEMORY,
|
||||||
|
ECUSTOM_HOST_CMD_GET_PARAM_MEMORY_SIZE,
|
||||||
ECUSTOM_HOST_CMD_SEND_RESULT,
|
ECUSTOM_HOST_CMD_SEND_RESULT,
|
||||||
#endif /* CONFIG_ESPI_PERIPHERAL_CUSTOM_OPCODE */
|
#endif /* CONFIG_ESPI_PERIPHERAL_CUSTOM_OPCODE */
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,9 +10,8 @@
|
||||||
#include <zephyr/kernel.h>
|
#include <zephyr/kernel.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#if !DT_HAS_CHOSEN(zephyr_ec_host_interface)
|
BUILD_ASSERT(DT_HAS_CHOSEN(zephyr_ec_host_interface),
|
||||||
#error Must chose zephyr,ec-host-interface in device tree
|
"Must choose zephyr,ec-host-interface in device tree");
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DT_HOST_CMD_DEV DT_CHOSEN(zephyr_ec_host_interface)
|
#define DT_HOST_CMD_DEV DT_CHOSEN(zephyr_ec_host_interface)
|
||||||
|
|
||||||
|
@ -82,9 +81,10 @@ static void handle_host_cmds_entry(void *arg1, void *arg2, void *arg3)
|
||||||
*/
|
*/
|
||||||
send_error_response(ec_host_cmd_dev,
|
send_error_response(ec_host_cmd_dev,
|
||||||
EC_HOST_CMD_ERROR);
|
EC_HOST_CMD_ERROR);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
/* rx buf and len now have valid incoming data */
|
|
||||||
|
|
||||||
|
/* rx buf and len now have valid incoming data */
|
||||||
if (*rx.len < RX_HEADER_SIZE) {
|
if (*rx.len < RX_HEADER_SIZE) {
|
||||||
send_error_response(ec_host_cmd_dev,
|
send_error_response(ec_host_cmd_dev,
|
||||||
EC_HOST_CMD_REQUEST_TRUNCATED);
|
EC_HOST_CMD_REQUEST_TRUNCATED);
|
||||||
|
@ -182,6 +182,7 @@ static void handle_host_cmds_entry(void *arg1, void *arg2, void *arg3)
|
||||||
tx_header->prtcl_ver = 3;
|
tx_header->prtcl_ver = 3;
|
||||||
tx_header->result = EC_HOST_CMD_SUCCESS;
|
tx_header->result = EC_HOST_CMD_SUCCESS;
|
||||||
tx_header->data_len = args.output_buf_size;
|
tx_header->data_len = args.output_buf_size;
|
||||||
|
tx_header->reserved = 0;
|
||||||
|
|
||||||
const uint16_t tx_valid_data_size =
|
const uint16_t tx_valid_data_size =
|
||||||
tx_header->data_len + TX_HEADER_SIZE;
|
tx_header->data_len + TX_HEADER_SIZE;
|
||||||
|
@ -192,6 +193,7 @@ static void handle_host_cmds_entry(void *arg1, void *arg2, void *arg3)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate checksum */
|
/* Calculate checksum */
|
||||||
|
tx_header->checksum = 0;
|
||||||
tx_header->checksum =
|
tx_header->checksum =
|
||||||
cal_checksum(tx_buffer, tx_valid_data_size);
|
cal_checksum(tx_buffer, tx_valid_data_size);
|
||||||
|
|
||||||
|
@ -199,6 +201,7 @@ static void handle_host_cmds_entry(void *arg1, void *arg2, void *arg3)
|
||||||
.buf = tx_buffer,
|
.buf = tx_buffer,
|
||||||
.len = tx_valid_data_size,
|
.len = tx_valid_data_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
ec_host_cmd_periph_send(ec_host_cmd_dev, &tx);
|
ec_host_cmd_periph_send(ec_host_cmd_dev, &tx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue