ec_host_cmd_periph: add device API

The host command peripheral device API abstracts how an embedded
controller sends and receives data from a host on a bus. Each bus like
eSPI, SPI, or I2C would implement their own host command peripheral
device. Each hardware device would then handle the necessary hardware
access to send and receive data over that bus.

The chosen host command peripheral device will be used by the host
command handler framework to send and receive host data correctly.

Signed-off-by: Jett Rink <jettrink@google.com>
This commit is contained in:
Jett Rink 2020-08-31 15:55:48 -06:00 committed by Anas Nashif
commit 703fe86220
11 changed files with 350 additions and 0 deletions

View file

@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_library()
zephyr_library_sources_ifdef(
CONFIG_EC_HOST_CMD_SIMULATOR
ec_host_cmd_simulator.c)
zephyr_library_sources_ifdef(CONFIG_USERSPACE ec_host_cmd_periph_handlers.c)

View file

@ -0,0 +1,20 @@
# Host Command Peripheral simulator config
# Copyright (c) 2020 Google LLC
# SPDX-License-Identifier: Apache-2.0
menuconfig EC_HOST_CMD_PERIPH
bool "Embedded Controller Host Command peripheral support"
help
Enable the embedded controller host command peripheral driver. This
is needed by the EC host command framework to send and receive data
on the appropriate EC host bus.
if EC_HOST_CMD_PERIPH
config EC_HOST_CMD_SIMULATOR
bool "Embedded Controller Host Command Peripheral Simulator"
help
Enable the EC host command simulator.
endif # EC_HOST_CMD_PERIPH

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2020 Google LLC
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <drivers/ec_host_cmd_periph.h>
#include <syscall_handler.h>
static inline void
z_vrfy_ec_host_cmd_periph_init(const struct device *dev,
struct ec_host_cmd_periph_rx_ctx *rx_ctx)
{
struct ec_host_cmd_periph_rx_ctx local_rx_ctx;
Z_OOPS(Z_SYSCALL_OBJ_INIT(dev, K_OBJ_DRIVER_EC_HOST_CMD_PERIPH_API));
z_impl_host_cmd_periph_init(dev, &local_rx_ctx);
Z_OOPS(z_user_to_copy(&local_rx_ctx, rx_ctx, sizeof(*rx_ctx)));
}
#include <syscalls/ec_host_cmd_periph_init_mrsh.c>
static inline void
z_vrfy_ec_host_cmd_periph_send(const struct device *dev,
const struct ec_host_cmd_periph_tx_buf *tx_buf)
{
struct ec_host_cmd_periph_tx_buf local_tx_buf;
Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_EC_HOST_CMD_PERIPH_API));
Z_OOPS(z_user_from_copy(&local_tx_buf, tx_buf, sizeof(*tx_buf)));
/* Ensure that user thread has acces to read buffer since
* device will read from this memory location.
*/
Z_OOPS(Z_SYSCALL_MEMORY_READ(local_tx_buf.buf, local_tx_buf.size));
z_impl_host_cmd_periph_send(dev, &local_tx_buf);
}
#include <syscalls/ec_host_cmd_periph_init_mrsh.c>

View file

@ -0,0 +1,85 @@
/*
* Copyright (c) 2020 Google LLC
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT zephyr_sim_ec_host_cmd_periph
#include <device.h>
#include <drivers/ec_host_cmd_periph.h>
#include <string.h>
#ifndef CONFIG_ARCH_POSIX
#error Simulator only valid on posix
#endif
static uint8_t rx_buffer[256];
static size_t rx_buffer_len;
/* Allow writing to rx buff at startup and block on reading. */
static K_SEM_DEFINE(handler_owns, 0, 1);
static K_SEM_DEFINE(dev_owns, 1, 1);
static ec_host_cmd_periph_api_send tx;
int ec_host_cmd_periph_sim_init(const struct device *dev,
struct ec_host_cmd_periph_rx_ctx *rx_ctx)
{
if (rx_ctx == NULL) {
return -EINVAL;
}
rx_ctx->buf = rx_buffer;
rx_ctx->len = &rx_buffer_len;
rx_ctx->dev_owns = &dev_owns;
rx_ctx->handler_owns = &handler_owns;
return 0;
}
int ec_host_cmd_periph_sim_send(const struct device *dev,
const struct ec_host_cmd_periph_tx_buf *buf)
{
if (tx != NULL) {
return tx(dev, buf);
}
return 0;
}
void ec_host_cmd_periph_sim_install_send_cb(ec_host_cmd_periph_api_send cb)
{
tx = cb;
}
int ec_host_cmd_periph_sim_data_received(const uint8_t *buffer, size_t len)
{
if (sizeof(rx_buffer) < len) {
return -ENOMEM;
}
if (k_sem_take(&dev_owns, K_NO_WAIT) != 0) {
return -EBUSY;
}
memcpy(rx_buffer, buffer, len);
rx_buffer_len = len;
k_sem_give(&handler_owns);
return 0;
}
static const struct ec_host_cmd_periph_api ec_host_cmd_api = {
.init = &ec_host_cmd_periph_sim_init,
.send = &ec_host_cmd_periph_sim_send,
};
static int ec_host_cmd_sim_init(const struct device *dev)
{
return 0;
}
/* Assume only one simulator */
DEVICE_AND_API_INIT(ec_host_cmd_simulator, DT_INST_LABEL(0),
ec_host_cmd_sim_init, NULL, NULL, POST_KERNEL,
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &ec_host_cmd_api);