From 703fe86220f0693f4f310ddd6a9da6a860862708 Mon Sep 17 00:00:00 2001 From: Jett Rink Date: Mon, 31 Aug 2020 15:55:48 -0600 Subject: [PATCH] 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 --- CODEOWNERS | 1 + boards/posix/native_posix/native_posix.dts | 7 + drivers/CMakeLists.txt | 1 + drivers/Kconfig | 2 + drivers/ec_host_cmd_periph/CMakeLists.txt | 8 ++ drivers/ec_host_cmd_periph/Kconfig | 20 +++ .../ec_host_cmd_periph_handlers.c | 40 ++++++ .../ec_host_cmd_simulator.c | 85 +++++++++++ .../zephyr,sim-ec-host-cmd-periph.yaml | 11 ++ include/drivers/ec_host_cmd_periph.h | 133 ++++++++++++++++++ .../ec_host_cmd_simulator.h | 42 ++++++ 11 files changed, 350 insertions(+) create mode 100644 drivers/ec_host_cmd_periph/CMakeLists.txt create mode 100644 drivers/ec_host_cmd_periph/Kconfig create mode 100644 drivers/ec_host_cmd_periph/ec_host_cmd_periph_handlers.c create mode 100644 drivers/ec_host_cmd_periph/ec_host_cmd_simulator.c create mode 100644 dts/bindings/ec_host_cmd_perhip/zephyr,sim-ec-host-cmd-periph.yaml create mode 100644 include/drivers/ec_host_cmd_periph.h create mode 100644 include/drivers/ec_host_cmd_periph/ec_host_cmd_simulator.h diff --git a/CODEOWNERS b/CODEOWNERS index ec50aac245f..61561fa25e2 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -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 diff --git a/boards/posix/native_posix/native_posix.dts b/boards/posix/native_posix/native_posix.dts index 708cc6698b2..639bacfe508 100644 --- a/boards/posix/native_posix/native_posix.dts +++ b/boards/posix/native_posix/native_posix.dts @@ -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"; + }; + }; diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index d409fabd45a..db17b7db98a 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -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) diff --git a/drivers/Kconfig b/drivers/Kconfig index 2952fe458e5..eafe17c5ca7 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -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" diff --git a/drivers/ec_host_cmd_periph/CMakeLists.txt b/drivers/ec_host_cmd_periph/CMakeLists.txt new file mode 100644 index 00000000000..2df8e17d644 --- /dev/null +++ b/drivers/ec_host_cmd_periph/CMakeLists.txt @@ -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) diff --git a/drivers/ec_host_cmd_periph/Kconfig b/drivers/ec_host_cmd_periph/Kconfig new file mode 100644 index 00000000000..fa240115734 --- /dev/null +++ b/drivers/ec_host_cmd_periph/Kconfig @@ -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 diff --git a/drivers/ec_host_cmd_periph/ec_host_cmd_periph_handlers.c b/drivers/ec_host_cmd_periph/ec_host_cmd_periph_handlers.c new file mode 100644 index 00000000000..00f0672f4ef --- /dev/null +++ b/drivers/ec_host_cmd_periph/ec_host_cmd_periph_handlers.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +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 + +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 diff --git a/drivers/ec_host_cmd_periph/ec_host_cmd_simulator.c b/drivers/ec_host_cmd_periph/ec_host_cmd_simulator.c new file mode 100644 index 00000000000..b6661e3e3a8 --- /dev/null +++ b/drivers/ec_host_cmd_periph/ec_host_cmd_simulator.c @@ -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 +#include +#include + +#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); diff --git a/dts/bindings/ec_host_cmd_perhip/zephyr,sim-ec-host-cmd-periph.yaml b/dts/bindings/ec_host_cmd_perhip/zephyr,sim-ec-host-cmd-periph.yaml new file mode 100644 index 00000000000..a6b12b8d402 --- /dev/null +++ b/dts/bindings/ec_host_cmd_perhip/zephyr,sim-ec-host-cmd-periph.yaml @@ -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 diff --git a/include/drivers/ec_host_cmd_periph.h b/include/drivers/ec_host_cmd_periph.h new file mode 100644 index 00000000000..7acc5a7e32b --- /dev/null +++ b/include/drivers/ec_host_cmd_periph.h @@ -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 +#include +#include + +#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 + +#endif /* ZEPHYR_INCLUDE_DRIVERS_HOST_CMD_PERIPH_H_ */ diff --git a/include/drivers/ec_host_cmd_periph/ec_host_cmd_simulator.h b/include/drivers/ec_host_cmd_periph/ec_host_cmd_simulator.h new file mode 100644 index 00000000000..14ba31fe8c8 --- /dev/null +++ b/include/drivers/ec_host_cmd_periph/ec_host_cmd_simulator.h @@ -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 + +/** + * @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);