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
parent 35ad4e8632
commit 703fe86220
11 changed files with 350 additions and 0 deletions

View file

@ -169,6 +169,7 @@
/drivers/dma/*sam0* @Sizurka
/drivers/dma/dma_stm32* @cybertale
/drivers/dma/*pl330* @raveenp
/drivers/ec_host_cmd_periph/ @jettr
/drivers/eeprom/ @henrikbrixandersen
/drivers/eeprom/eeprom_stm32.c @KwonTae-young
/drivers/entropy/*rv32m1* @MaureenHelm

View file

@ -19,6 +19,7 @@
zephyr,flash = &flash0;
zephyr,entropy = &rng;
zephyr,flash-controller = &flashcontroller0;
zephyr,ec-host-interface = &hcp;
};
aliases {
@ -112,4 +113,10 @@
label = "COUNTER_0";
};
hcp: ec-host-cmd-periph {
status = "okay";
compatible = "zephyr,sim-ec-host-cmd-periph";
label = "EC_HOST_CMD_SIM";
};
};

View file

@ -14,6 +14,7 @@ add_subdirectory_ifdef(CONFIG_DAC dac)
add_subdirectory_ifdef(CONFIG_DISPLAY display)
add_subdirectory_ifdef(CONFIG_DMA dma)
add_subdirectory_ifdef(CONFIG_GPIO gpio)
add_subdirectory_ifdef(CONFIG_EC_HOST_CMD_PERIPH ec_host_cmd_periph)
add_subdirectory_ifdef(CONFIG_I2C i2c)
add_subdirectory_ifdef(CONFIG_I2S i2s)
add_subdirectory_ifdef(CONFIG_IEEE802154 ieee802154)

View file

@ -15,6 +15,8 @@ source "drivers/console/Kconfig"
source "drivers/debug/Kconfig"
source "drivers/ec_host_cmd_periph/Kconfig"
source "drivers/ethernet/Kconfig"
source "drivers/net/Kconfig"

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);

View file

@ -0,0 +1,11 @@
# SPDX-License-Identifier: Apache-2.0
description: Simulated Host Command Peripheral
compatible: "zephyr,sim-ec-host-cmd-periph"
include: base.yaml
properties:
label:
required: true

View file

@ -0,0 +1,133 @@
/*
* Copyright (c) 2020 Google LLC.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Public APIs for Host Command Peripherals that respond to host commands
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_HOST_CMD_PERIPH_H_
#define ZEPHYR_INCLUDE_DRIVERS_HOST_CMD_PERIPH_H_
#include <sys/__assert.h>
#include <zephyr/types.h>
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Host Command Peripherals API
* @defgroup ec_host_cmd_periph Host Command Peripherals API
* @ingroup io_interfaces
* @{
*/
/**
* @brief Context for host command peripheral and framework to pass rx data
*/
struct ec_host_cmd_periph_rx_ctx {
/** Buffer written to by device (when dev_owns) and read from by
* command framework and handler (when handler_owns). Buffer is owned
* by devices and lives as long as device is valid. Device will never
* read from this buffer (for security reasons).
*/
uint8_t *buf;
/** Number of bytes written to @a buf by device (when dev_owns). */
size_t *len;
/** Device will take when it needs to write to @a buf and @a size. */
struct k_sem *dev_owns;
/** Handler will take so it can read @a buf and @a size */
struct k_sem *handler_owns;
};
/**
* @brief Context for host command peripheral and framework to pass tx data
*/
struct ec_host_cmd_periph_tx_buf {
/** Data to write to the host */
void *buf;
/** Number of bytes to write from @a buf */
size_t len;
};
typedef int (*ec_host_cmd_periph_api_init)(
const struct device *dev, struct ec_host_cmd_periph_rx_ctx *rx_ctx);
typedef int (*ec_host_cmd_periph_api_send)(
const struct device *dev,
const struct ec_host_cmd_periph_tx_buf *tx_buf);
__subsystem struct ec_host_cmd_periph_api {
ec_host_cmd_periph_api_init init;
ec_host_cmd_periph_api_send send;
};
/**
* @brief Initialize a host command device
*
* This routine initializes a host command device, prior to its first use. The
* receive context object are an output of this function and are valid
* for the lifetime of this device. The RX context is used by the client to
* receive data from the host.
*
* @param dev Pointer to the device structure for the driver instance.
* @param rx_ctx [out] The receiving context object that are valid for the
* lifetime of the device. These objects are used to receive data
* from the driver when the host send data.
*
* @retval 0 if successful
*/
__syscall int ec_host_cmd_periph_init(const struct device *dev,
struct ec_host_cmd_periph_rx_ctx *rx_ctx);
static inline int
z_impl_ec_host_cmd_periph_init(const struct device *dev,
struct ec_host_cmd_periph_rx_ctx *rx_ctx)
{
const struct ec_host_cmd_periph_api *api =
(const struct ec_host_cmd_periph_api *)dev->api;
return api->init(dev, rx_ctx);
}
/**
* @brief Sends the specified data to the host
*
* Sends the data specified in @a tx_buf to the host over the host communication
* bus.
*
* @param dev Pointer to the device structure for the driver instance.
* @param tx_buf The data to transmit to the host.
*
* @retval 0 if successful
*/
__syscall int ec_host_cmd_periph_send(
const struct device *dev,
const struct ec_host_cmd_periph_tx_buf *tx_buf);
static inline int z_impl_ec_host_cmd_periph_send(
const struct device *dev,
const struct ec_host_cmd_periph_tx_buf *tx_buf)
{
const struct ec_host_cmd_periph_api *api =
(const struct ec_host_cmd_periph_api *)dev->api;
return api->send(dev, tx_buf);
}
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#include <syscalls/ec_host_cmd_periph.h>
#endif /* ZEPHYR_INCLUDE_DRIVERS_HOST_CMD_PERIPH_H_ */

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2020 Google LLC
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Header for commands to interact with the simulator outside of normal
* device interface.
*/
/* For ec_host_cmd_periph_api_send function pointer type */
#include <drivers/ec_host_cmd_periph.h>
/**
* @brief Install callback for when this device would sends data to host
*
* When this host command simulator device should send data to the host, it
* will call the the callback parameter provided by this function. Note that
* only one callback may be installed at a time. Calling this a second time
* will override the first callback installation.
*
* @param cb Callback that is called when device would send data to host.
*
* @return N/A
*/
void ec_host_cmd_periph_sim_install_send_cb(ec_host_cmd_periph_api_send cb);
/**
* @brief Simulate receiving data from host as passed in to this function
*
* Calling this function simulates that data was sent from the host to the DUT.
*
* @param buffer The buffer that contains the data to receive.
* @param len The number of bytes that are received from the above buffer.
*
* @retval 0 if successful
* @retval -ENOMEM if len is greater than the RX buffer size.
* @retval -EBUSY if the host command framework is busy with another request.
*/
int ec_host_cmd_periph_sim_data_received(const uint8_t *buffer, size_t len);