982 lines
33 KiB
C
982 lines
33 KiB
C
/*
|
|
* Copyright (c) 2019 Intel Corporation.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* @brief Public APIs for eSPI driver
|
|
*/
|
|
|
|
#ifndef ZEPHYR_INCLUDE_ESPI_H_
|
|
#define ZEPHYR_INCLUDE_ESPI_H_
|
|
|
|
#include <sys/__assert.h>
|
|
#include <zephyr/types.h>
|
|
#include <device.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* @brief eSPI Driver APIs
|
|
* @defgroup espi_interface ESPI Driver APIs
|
|
* @ingroup io_interfaces
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @brief eSPI I/O mode capabilities
|
|
*/
|
|
enum espi_io_mode {
|
|
ESPI_IO_MODE_SINGLE_LINE = BIT(0),
|
|
ESPI_IO_MODE_DUAL_LINES = BIT(1),
|
|
ESPI_IO_MODE_QUAD_LINES = BIT(2),
|
|
};
|
|
|
|
/**
|
|
*+----------------------------------------------------------------------+
|
|
*| |
|
|
*| eSPI host +-------------+ |
|
|
*| +-----------+ | Power | +----------+ |
|
|
*| |Out of band| | management | | GPIO | |
|
|
*| +------------+ |processor | | controller | | sources | |
|
|
*| | SPI flash | +-----------+ +-------------+ +----------+ |
|
|
*| | controller | | | | |
|
|
*| +------------+ | | | |
|
|
*| | | | +--------+ +---------------+ |
|
|
*| | | | | | |
|
|
*| | | +-----+ +--------+ +----------+ +----v-----+ |
|
|
*| | | | | LPC | | Tunneled | | Tunneled | |
|
|
*| | | | | bridge | | SMBus | | GPIO | |
|
|
*| | | | +--------+ +----------+ +----------+ |
|
|
*| | | | | | | |
|
|
*| | | | ------+ | | |
|
|
*| | | | | | | |
|
|
*| | | +------v-----+ +---v-------v-------------v----+ |
|
|
*| | | | eSPI Flash | | eSPI protocol block | |
|
|
*| | | | access +--->+ | |
|
|
*| | | +------------+ +------------------------------+ |
|
|
*| | | | |
|
|
*| | +-----------+ | |
|
|
*| | v v |
|
|
*| | XXXXXXXXXXXXXXXXXXXXXXX |
|
|
*| | XXXXXXXXXXXXXXXXXXXXX |
|
|
*| | XXXXXXXXXXXXXXXXXXX |
|
|
*+----------------------------------------------------------------------+
|
|
* | |
|
|
* v +-----------------+
|
|
* +---------+ | | | | | |
|
|
* | Flash | | | | | | |
|
|
* +---------+ | + + + + | eSPI bus
|
|
* | CH0 CH1 CH2 CH3 | (logical channels)
|
|
* | + + + + |
|
|
* | | | | | |
|
|
* +-----------------+
|
|
* |
|
|
*+-----------------------------------------------------------------------+
|
|
*| eSPI slave |
|
|
*| |
|
|
*| CH0 | CH1 | CH2 | CH3 |
|
|
*| eSPI endpoint | VWIRE | OOB | Flash |
|
|
*+-----------------------------------------------------------------------+
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* @brief eSPI channel.
|
|
*
|
|
* Identifies each eSPI logical channel supported by eSPI controller
|
|
* Each channel allows independent traffic, but the assignment of channel
|
|
* type to channel number is fixed.
|
|
*
|
|
* Note that generic commands are not associated with any channel, so traffic
|
|
* over eSPI can occur if all channels are disabled or not ready
|
|
*/
|
|
enum espi_channel {
|
|
ESPI_CHANNEL_PERIPHERAL = BIT(0),
|
|
ESPI_CHANNEL_VWIRE = BIT(1),
|
|
ESPI_CHANNEL_OOB = BIT(2),
|
|
ESPI_CHANNEL_FLASH = BIT(3),
|
|
};
|
|
|
|
/**
|
|
* @brief eSPI bus event.
|
|
*
|
|
* eSPI bus event to indicate events for which user can register callbacks
|
|
*/
|
|
enum espi_bus_event {
|
|
ESPI_BUS_RESET = BIT(0),
|
|
ESPI_BUS_EVENT_CHANNEL_READY = BIT(1),
|
|
ESPI_BUS_EVENT_VWIRE_RECEIVED = BIT(2),
|
|
ESPI_BUS_EVENT_OOB_RECEIVED = BIT(3),
|
|
ESPI_BUS_PERIPHERAL_NOTIFICATION = BIT(4),
|
|
};
|
|
|
|
/**
|
|
* @cond INTERNAL_HIDDEN
|
|
*
|
|
*/
|
|
#define ESPI_PERIPHERAL_INDEX_0 0ul
|
|
#define ESPI_PERIPHERAL_INDEX_1 1ul
|
|
#define ESPI_PERIPHERAL_INDEX_2 2ul
|
|
|
|
#define ESPI_SLAVE_TO_MASTER 0ul
|
|
#define ESPI_MASTER_TO_SLAVE 1ul
|
|
|
|
#define ESPI_VWIRE_SRC_ID0 0ul
|
|
#define ESPI_VWIRE_SRC_ID1 1ul
|
|
#define ESPI_VWIRE_SRC_ID2 2ul
|
|
#define ESPI_VWIRE_SRC_ID3 3ul
|
|
#define ESPI_VWIRE_SRC_ID_MAX 4ul
|
|
|
|
#define ESPI_PERIPHERAL_NODATA 0ul
|
|
|
|
#define E8042_START_OPCODE 0x50
|
|
#define E8042_MAX_OPCODE 0x5F
|
|
|
|
#define EACPI_START_OPCODE 0x60
|
|
#define EACPI_MAX_OPCODE 0x6F
|
|
|
|
#define ECUSTOM_START_OPCODE 0xF0
|
|
#define ECUSTOM_MAX_OPCODE 0xFF
|
|
|
|
/** @endcond */
|
|
|
|
/**
|
|
* @brief eSPI peripheral notification type.
|
|
*
|
|
* eSPI peripheral notification event details to indicate which peripheral
|
|
* trigger the eSPI callback
|
|
*/
|
|
enum espi_virtual_peripheral {
|
|
ESPI_PERIPHERAL_UART,
|
|
ESPI_PERIPHERAL_8042_KBC,
|
|
ESPI_PERIPHERAL_HOST_IO,
|
|
ESPI_PERIPHERAL_DEBUG_PORT80,
|
|
ESPI_PERIPHERAL_HOST_IO_PVT,
|
|
#if defined(CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD)
|
|
ESPI_PERIPHERAL_EC_HOST_CMD,
|
|
#endif /* CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD */
|
|
};
|
|
|
|
/**
|
|
* @brief eSPI cycle types supported over eSPI peripheral channel
|
|
*/
|
|
enum espi_cycle_type {
|
|
ESPI_CYCLE_MEMORY_READ32,
|
|
ESPI_CYCLE_MEMORY_READ64,
|
|
ESPI_CYCLE_MEMORY_WRITE32,
|
|
ESPI_CYCLE_MEMORY_WRITE64,
|
|
ESPI_CYCLE_MESSAGE_NODATA,
|
|
ESPI_CYCLE_MESSAGE_DATA,
|
|
ESPI_CYCLE_OK_COMPLETION_NODATA,
|
|
ESPI_CYCLE_OKCOMPLETION_DATA,
|
|
ESPI_CYCLE_NOK_COMPLETION_NODATA,
|
|
};
|
|
|
|
/**
|
|
* @brief eSPI system platform signals that can be send or receive through
|
|
* virtual wire channel
|
|
*/
|
|
enum espi_vwire_signal {
|
|
/* Virtual wires that can only be send from master to slave */
|
|
ESPI_VWIRE_SIGNAL_SLP_S3,
|
|
ESPI_VWIRE_SIGNAL_SLP_S4,
|
|
ESPI_VWIRE_SIGNAL_SLP_S5,
|
|
ESPI_VWIRE_SIGNAL_OOB_RST_WARN,
|
|
ESPI_VWIRE_SIGNAL_PLTRST,
|
|
ESPI_VWIRE_SIGNAL_SUS_STAT,
|
|
ESPI_VWIRE_SIGNAL_NMIOUT,
|
|
ESPI_VWIRE_SIGNAL_SMIOUT,
|
|
ESPI_VWIRE_SIGNAL_HOST_RST_WARN,
|
|
ESPI_VWIRE_SIGNAL_SLP_A,
|
|
ESPI_VWIRE_SIGNAL_SUS_PWRDN_ACK,
|
|
ESPI_VWIRE_SIGNAL_SUS_WARN,
|
|
ESPI_VWIRE_SIGNAL_SLP_WLAN,
|
|
ESPI_VWIRE_SIGNAL_SLP_LAN,
|
|
ESPI_VWIRE_SIGNAL_HOST_C10,
|
|
ESPI_VWIRE_SIGNAL_DNX_WARN,
|
|
/* Virtual wires that can only be send from slave to master */
|
|
ESPI_VWIRE_SIGNAL_PME,
|
|
ESPI_VWIRE_SIGNAL_WAKE,
|
|
ESPI_VWIRE_SIGNAL_OOB_RST_ACK,
|
|
ESPI_VWIRE_SIGNAL_SLV_BOOT_STS,
|
|
ESPI_VWIRE_SIGNAL_ERR_NON_FATAL,
|
|
ESPI_VWIRE_SIGNAL_ERR_FATAL,
|
|
ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE,
|
|
ESPI_VWIRE_SIGNAL_HOST_RST_ACK,
|
|
ESPI_VWIRE_SIGNAL_RST_CPU_INIT,
|
|
/* System management interrupt */
|
|
ESPI_VWIRE_SIGNAL_SMI,
|
|
/* System control interrupt */
|
|
ESPI_VWIRE_SIGNAL_SCI,
|
|
ESPI_VWIRE_SIGNAL_DNX_ACK,
|
|
ESPI_VWIRE_SIGNAL_SUS_ACK,
|
|
};
|
|
|
|
/* eSPI LPC peripherals. */
|
|
enum lpc_peripheral_opcode {
|
|
/* Read transactions */
|
|
E8042_OBF_HAS_CHAR = 0x50,
|
|
E8042_IBF_HAS_CHAR,
|
|
/* Write transactions */
|
|
E8042_WRITE_KB_CHAR,
|
|
E8042_WRITE_MB_CHAR,
|
|
/* Write transactions without input parameters */
|
|
E8042_RESUME_IRQ,
|
|
E8042_PAUSE_IRQ,
|
|
E8042_CLEAR_OBF,
|
|
/* Status transactions */
|
|
E8042_READ_KB_STS,
|
|
E8042_SET_FLAG,
|
|
E8042_CLEAR_FLAG,
|
|
/* ACPI read transactions */
|
|
EACPI_OBF_HAS_CHAR = EACPI_START_OPCODE,
|
|
EACPI_IBF_HAS_CHAR,
|
|
/* ACPI write transactions */
|
|
EACPI_WRITE_CHAR,
|
|
/* ACPI status transactions */
|
|
EACPI_READ_STS,
|
|
EACPI_WRITE_STS,
|
|
#if defined(CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION)
|
|
/* Shared memory region support to return the ACPI response data */
|
|
EACPI_GET_SHARED_MEMORY,
|
|
#endif /* CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION */
|
|
#if defined(CONFIG_ESPI_PERIPHERAL_CUSTOM_OPCODE)
|
|
/* Other customized transactions */
|
|
ECUSTOM_HOST_SUBS_INTERRUPT_EN = ECUSTOM_START_OPCODE,
|
|
ECUSTOM_HOST_CMD_GET_PARAM_MEMORY,
|
|
ECUSTOM_HOST_CMD_SEND_RESULT,
|
|
#endif /* CONFIG_ESPI_PERIPHERAL_CUSTOM_OPCODE */
|
|
};
|
|
|
|
/* KBC 8042 event: Input Buffer Full */
|
|
#define HOST_KBC_EVT_IBF BIT(0)
|
|
/* KBC 8042 event: Output Buffer Empty */
|
|
#define HOST_KBC_EVT_OBE BIT(1)
|
|
/**
|
|
* @brief Bit field definition of evt_data in struct espi_event for KBC.
|
|
*/
|
|
struct espi_evt_data_kbc {
|
|
uint32_t type:8;
|
|
uint32_t data:8;
|
|
uint32_t evt:8;
|
|
uint32_t reserved:8;
|
|
};
|
|
|
|
/**
|
|
* @brief Bit field definition of evt_data in struct espi_event for ACPI.
|
|
*/
|
|
struct espi_evt_data_acpi {
|
|
uint32_t type:8;
|
|
uint32_t data:8;
|
|
uint32_t reserved:16;
|
|
};
|
|
|
|
/**
|
|
* @brief eSPI event
|
|
*/
|
|
struct espi_event {
|
|
/** Event type */
|
|
enum espi_bus_event evt_type;
|
|
/** Additional details for bus event type */
|
|
uint32_t evt_details;
|
|
/** Data associated to the event */
|
|
uint32_t evt_data;
|
|
};
|
|
|
|
/**
|
|
* @brief eSPI bus configuration parameters
|
|
*/
|
|
struct espi_cfg {
|
|
/** Supported I/O mode */
|
|
enum espi_io_mode io_caps;
|
|
/** Supported channels */
|
|
enum espi_channel channel_caps;
|
|
/** Maximum supported frequency in MHz */
|
|
uint8_t max_freq;
|
|
};
|
|
|
|
/**
|
|
* @brief eSPI peripheral request packet format
|
|
*/
|
|
struct espi_request_packet {
|
|
enum espi_cycle_type cycle_type;
|
|
uint8_t tag;
|
|
uint16_t len;
|
|
uint32_t address;
|
|
uint8_t *data;
|
|
};
|
|
|
|
/**
|
|
* @brief eSPI out-of-band transaction packet format
|
|
*/
|
|
struct espi_oob_packet {
|
|
uint8_t *buf;
|
|
uint16_t len;
|
|
};
|
|
|
|
/**
|
|
* @brief eSPI flash transactions packet format
|
|
*/
|
|
struct espi_flash_packet {
|
|
uint8_t *buf;
|
|
uint32_t flash_addr;
|
|
uint16_t len;
|
|
};
|
|
|
|
struct espi_callback;
|
|
|
|
/**
|
|
* @typedef espi_callback_handler_t
|
|
* @brief Define the application callback handler function signature.
|
|
*
|
|
* @param dev Device struct for the eSPI device.
|
|
* @param cb Original struct espi_callback owning this handler.
|
|
* @param espi_evt event details that trigger the callback handler.
|
|
*
|
|
*/
|
|
typedef void (*espi_callback_handler_t) (const struct device *dev,
|
|
struct espi_callback *cb,
|
|
struct espi_event espi_evt);
|
|
|
|
/**
|
|
* @cond INTERNAL_HIDDEN
|
|
*
|
|
* Used to register a callback in the driver instance callback list.
|
|
* As many callbacks as needed can be added as long as each of them
|
|
* are unique pointers of struct espi_callback.
|
|
* Beware such structure should not be allocated on stack.
|
|
*
|
|
* Note: To help setting it, see espi_init_callback() below
|
|
*/
|
|
struct espi_callback {
|
|
/** This is meant to be used in the driver only */
|
|
sys_snode_t node;
|
|
|
|
/** Actual callback function being called when relevant */
|
|
espi_callback_handler_t handler;
|
|
|
|
/** An event which user is interested in, if 0 the callback
|
|
* will never be called. Such evt_mask can be modified whenever
|
|
* necessary by the owner, and thus will affect the handler being
|
|
* called or not.
|
|
*/
|
|
enum espi_bus_event evt_type;
|
|
};
|
|
/** @endcond */
|
|
|
|
/**
|
|
* @cond INTERNAL_HIDDEN
|
|
*
|
|
* eSPI driver API definition and system call entry points
|
|
*
|
|
* (Internal use only.)
|
|
*/
|
|
typedef int (*espi_api_config)(const struct device *dev, struct espi_cfg *cfg);
|
|
typedef bool (*espi_api_get_channel_status)(const struct device *dev,
|
|
enum espi_channel ch);
|
|
/* Logical Channel 0 APIs */
|
|
typedef int (*espi_api_read_request)(const struct device *dev,
|
|
struct espi_request_packet *req);
|
|
typedef int (*espi_api_write_request)(const struct device *dev,
|
|
struct espi_request_packet *req);
|
|
typedef int (*espi_api_lpc_read_request)(const struct device *dev,
|
|
enum lpc_peripheral_opcode op,
|
|
uint32_t *data);
|
|
typedef int (*espi_api_lpc_write_request)(const struct device *dev,
|
|
enum lpc_peripheral_opcode op,
|
|
uint32_t *data);
|
|
/* Logical Channel 1 APIs */
|
|
typedef int (*espi_api_send_vwire)(const struct device *dev,
|
|
enum espi_vwire_signal vw,
|
|
uint8_t level);
|
|
typedef int (*espi_api_receive_vwire)(const struct device *dev,
|
|
enum espi_vwire_signal vw,
|
|
uint8_t *level);
|
|
/* Logical Channel 2 APIs */
|
|
typedef int (*espi_api_send_oob)(const struct device *dev,
|
|
struct espi_oob_packet *pckt);
|
|
typedef int (*espi_api_receive_oob)(const struct device *dev,
|
|
struct espi_oob_packet *pckt);
|
|
/* Logical Channel 3 APIs */
|
|
typedef int (*espi_api_flash_read)(const struct device *dev,
|
|
struct espi_flash_packet *pckt);
|
|
typedef int (*espi_api_flash_write)(const struct device *dev,
|
|
struct espi_flash_packet *pckt);
|
|
typedef int (*espi_api_flash_erase)(const struct device *dev,
|
|
struct espi_flash_packet *pckt);
|
|
/* Callbacks and traffic intercept */
|
|
typedef int (*espi_api_manage_callback)(const struct device *dev,
|
|
struct espi_callback *callback,
|
|
bool set);
|
|
|
|
__subsystem struct espi_driver_api {
|
|
espi_api_config config;
|
|
espi_api_get_channel_status get_channel_status;
|
|
espi_api_read_request read_request;
|
|
espi_api_write_request write_request;
|
|
espi_api_lpc_read_request read_lpc_request;
|
|
espi_api_lpc_write_request write_lpc_request;
|
|
espi_api_send_vwire send_vwire;
|
|
espi_api_receive_vwire receive_vwire;
|
|
espi_api_send_oob send_oob;
|
|
espi_api_receive_oob receive_oob;
|
|
espi_api_flash_read flash_read;
|
|
espi_api_flash_write flash_write;
|
|
espi_api_flash_erase flash_erase;
|
|
espi_api_manage_callback manage_callback;
|
|
};
|
|
|
|
/**
|
|
* @endcond
|
|
*/
|
|
|
|
/**
|
|
* @brief Configure operation of a eSPI controller.
|
|
*
|
|
* This routine provides a generic interface to override eSPI controller
|
|
* capabilities.
|
|
*
|
|
* If this eSPI controller is acting as slave, the values set here
|
|
* will be discovered as part through the GET_CONFIGURATION command
|
|
* issued by the eSPI master during initialization.
|
|
*
|
|
* If this eSPI controller is acting as master, the values set here
|
|
* will be used by eSPI master to determine minimum common capabilities with
|
|
* eSPI slave then send via SET_CONFIGURATION command.
|
|
*
|
|
* +--------+ +---------+ +------+ +---------+ +---------+
|
|
* | eSPI | | eSPI | | eSPI | | eSPI | | eSPI |
|
|
* | slave | | driver | | bus | | driver | | host |
|
|
* +--------+ +---------+ +------+ +---------+ +---------+
|
|
* | | | | |
|
|
* | espi_config | Set eSPI | Set eSPI | espi_config |
|
|
* +--------------+ ctrl regs | cap ctrl reg| +-----------+
|
|
* | +-------+ | +--------+ |
|
|
* | |<------+ | +------->| |
|
|
* | | | | |
|
|
* | | | | |
|
|
* | | | GET_CONFIGURATION | |
|
|
* | | +<------------------+ |
|
|
* | |<-----------| | |
|
|
* | | eSPI caps | | |
|
|
* | |----------->+ response | |
|
|
* | | |------------------>+ |
|
|
* | | | | |
|
|
* | | | SET_CONFIGURATION | |
|
|
* | | +<------------------+ |
|
|
* | | | accept | |
|
|
* | | +------------------>+ |
|
|
* + + + + +
|
|
*
|
|
* @param dev Pointer to the device structure for the driver instance.
|
|
* @param cfg the device runtime configuration for the eSPI controller.
|
|
*
|
|
* @retval 0 If successful.
|
|
* @retval -EIO General input / output error, failed to configure device.
|
|
* @retval -EINVAL invalid capabilities, failed to configure device.
|
|
* @retval -ENOTSUP capability not supported by eSPI slave.
|
|
*/
|
|
__syscall int espi_config(const struct device *dev, struct espi_cfg *cfg);
|
|
|
|
static inline int z_impl_espi_config(const struct device *dev,
|
|
struct espi_cfg *cfg)
|
|
{
|
|
const struct espi_driver_api *api =
|
|
(const struct espi_driver_api *)dev->api;
|
|
|
|
return api->config(dev, cfg);
|
|
}
|
|
|
|
/**
|
|
* @brief Query to see if it a channel is ready.
|
|
*
|
|
* This routine allows to check if logical channel is ready before use.
|
|
* Note that queries for channels not supported will always return false.
|
|
*
|
|
* @param dev Pointer to the device structure for the driver instance.
|
|
* @param ch the eSPI channel for which status is to be retrieved.
|
|
*
|
|
* @retval true If eSPI channel is ready.
|
|
* @retval false otherwise.
|
|
*/
|
|
__syscall bool espi_get_channel_status(const struct device *dev,
|
|
enum espi_channel ch);
|
|
|
|
static inline bool z_impl_espi_get_channel_status(const struct device *dev,
|
|
enum espi_channel ch)
|
|
{
|
|
const struct espi_driver_api *api =
|
|
(const struct espi_driver_api *)dev->api;
|
|
|
|
return api->get_channel_status(dev, ch);
|
|
}
|
|
|
|
/**
|
|
* @brief Sends memory, I/O or message read request over eSPI.
|
|
*
|
|
* This routines provides a generic interface to send a read request packet.
|
|
*
|
|
* @param dev Pointer to the device structure for the driver instance.
|
|
* @param req Address of structure representing a memory,
|
|
* I/O or message read request.
|
|
*
|
|
* @retval 0 If successful.
|
|
* @retval -ENOTSUP if eSPI controller doesn't support raw packets and instead
|
|
* low memory transactions are handled by controller hardware directly.
|
|
* @retval -EIO General input / output error, failed to send over the bus.
|
|
*/
|
|
__syscall int espi_read_request(const struct device *dev,
|
|
struct espi_request_packet *req);
|
|
|
|
static inline int z_impl_espi_read_request(const struct device *dev,
|
|
struct espi_request_packet *req)
|
|
{
|
|
const struct espi_driver_api *api =
|
|
(const struct espi_driver_api *)dev->api;
|
|
|
|
if (!api->read_request) {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
return api->read_request(dev, req);
|
|
}
|
|
|
|
/**
|
|
* @brief Sends memory, I/O or message write request over eSPI.
|
|
*
|
|
* This routines provides a generic interface to send a write request packet.
|
|
*
|
|
* @param dev Pointer to the device structure for the driver instance.
|
|
* @param req Address of structure representing a memory, I/O or
|
|
* message write request.
|
|
*
|
|
* @retval 0 If successful.
|
|
* @retval -ENOTSUP if eSPI controller doesn't support raw packets and instead
|
|
* low memory transactions are handled by controller hardware directly.
|
|
* @retval -EINVAL General input / output error, failed to send over the bus.
|
|
*/
|
|
__syscall int espi_write_request(const struct device *dev,
|
|
struct espi_request_packet *req);
|
|
|
|
static inline int z_impl_espi_write_request(const struct device *dev,
|
|
struct espi_request_packet *req)
|
|
{
|
|
const struct espi_driver_api *api =
|
|
(const struct espi_driver_api *)dev->api;
|
|
|
|
if (!api->write_request) {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
return api->write_request(dev, req);
|
|
}
|
|
|
|
/**
|
|
* @brief Reads SOC data from a LPC peripheral with information
|
|
* updated over eSPI.
|
|
*
|
|
* This routine provides a generic interface to read a block whose
|
|
* information was updated by an eSPI transaction. Reading may trigger
|
|
* a transaction. The eSPI packet is assembled by the HW block.
|
|
*
|
|
* @param dev Pointer to the device structure for the driver instance.
|
|
* @param op Enum representing opcode for peripheral type and read request.
|
|
* @param data Parameter to be read from to the LPC peripheral.
|
|
*
|
|
* @retval 0 If successful.
|
|
* @retval -ENOTSUP if eSPI peripheral is off or not supported.
|
|
* @retval -EINVAL for unimplemented lpc opcode, but in range.
|
|
*/
|
|
__syscall int espi_read_lpc_request(const struct device *dev,
|
|
enum lpc_peripheral_opcode op,
|
|
uint32_t *data);
|
|
|
|
static inline int z_impl_espi_read_lpc_request(const struct device *dev,
|
|
enum lpc_peripheral_opcode op,
|
|
uint32_t *data)
|
|
{
|
|
const struct espi_driver_api *api =
|
|
(const struct espi_driver_api *)dev->api;
|
|
|
|
if (!api->read_lpc_request) {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
return api->read_lpc_request(dev, op, data);
|
|
}
|
|
|
|
/**
|
|
* @brief Writes data to a LPC peripheral which generates an eSPI transaction.
|
|
*
|
|
* This routine provides a generic interface to write data to a block which
|
|
* triggers an eSPI transaction. The eSPI packet is assembled by the HW
|
|
* block.
|
|
*
|
|
* @param dev Pointer to the device structure for the driver instance.
|
|
* @param op Enum representing an opcode for peripheral type and write request.
|
|
* @param data Represents the parameter passed to the LPC peripheral.
|
|
*
|
|
* @retval 0 If successful.
|
|
* @retval -ENOTSUP if eSPI peripheral is off or not supported.
|
|
* @retval -EINVAL for unimplemented lpc opcode, but in range.
|
|
*/
|
|
__syscall int espi_write_lpc_request(const struct device *dev,
|
|
enum lpc_peripheral_opcode op,
|
|
uint32_t *data);
|
|
|
|
static inline int z_impl_espi_write_lpc_request(const struct device *dev,
|
|
enum lpc_peripheral_opcode op,
|
|
uint32_t *data)
|
|
{
|
|
const struct espi_driver_api *api =
|
|
(const struct espi_driver_api *)dev->api;
|
|
|
|
if (!api->write_lpc_request) {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
return api->write_lpc_request(dev, op, data);
|
|
}
|
|
|
|
/**
|
|
* @brief Sends system/platform signal as a virtual wire packet.
|
|
*
|
|
* This routines provides a generic interface to send a virtual wire packet
|
|
* from slave to master.
|
|
*
|
|
* @param dev Pointer to the device structure for the driver instance.
|
|
* @param signal The signal to be send to eSPI master.
|
|
* @param level The level of signal requested LOW or HIGH.
|
|
*
|
|
* @retval 0 If successful.
|
|
* @retval -EIO General input / output error, failed to send over the bus.
|
|
*/
|
|
__syscall int espi_send_vwire(const struct device *dev,
|
|
enum espi_vwire_signal signal,
|
|
uint8_t level);
|
|
|
|
static inline int z_impl_espi_send_vwire(const struct device *dev,
|
|
enum espi_vwire_signal signal,
|
|
uint8_t level)
|
|
{
|
|
const struct espi_driver_api *api =
|
|
(const struct espi_driver_api *)dev->api;
|
|
|
|
return api->send_vwire(dev, signal, level);
|
|
}
|
|
|
|
/**
|
|
* @brief Retrieves level status for a signal encapsulated in a virtual wire.
|
|
*
|
|
* This routines provides a generic interface to request a virtual wire packet
|
|
* from eSPI master and retrieve the signal level.
|
|
*
|
|
* @param dev Pointer to the device structure for the driver instance.
|
|
* @param signal the signal to be requested from eSPI master.
|
|
* @param level the level of signal requested 0b LOW, 1b HIGH.
|
|
*
|
|
* @retval -EIO General input / output error, failed request to master.
|
|
*/
|
|
__syscall int espi_receive_vwire(const struct device *dev,
|
|
enum espi_vwire_signal signal,
|
|
uint8_t *level);
|
|
|
|
static inline int z_impl_espi_receive_vwire(const struct device *dev,
|
|
enum espi_vwire_signal signal,
|
|
uint8_t *level)
|
|
{
|
|
const struct espi_driver_api *api =
|
|
(const struct espi_driver_api *)dev->api;
|
|
|
|
return api->receive_vwire(dev, signal, level);
|
|
}
|
|
|
|
/**
|
|
* @brief Sends SMBus transaction (out-of-band) packet over eSPI bus.
|
|
*
|
|
* This routines provides an interface to encapsulate a SMBus transaction
|
|
* and send into packet over eSPI bus
|
|
*
|
|
* @param dev Pointer to the device structure for the driver instance.
|
|
* @param pckt Address of the packet representation of SMBus transaction.
|
|
*
|
|
* @retval -EIO General input / output error, failed request to master.
|
|
*/
|
|
__syscall int espi_send_oob(const struct device *dev,
|
|
struct espi_oob_packet *pckt);
|
|
|
|
static inline int z_impl_espi_send_oob(const struct device *dev,
|
|
struct espi_oob_packet *pckt)
|
|
{
|
|
const struct espi_driver_api *api =
|
|
(const struct espi_driver_api *)dev->api;
|
|
|
|
if (!api->send_oob) {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
return api->send_oob(dev, pckt);
|
|
}
|
|
|
|
/**
|
|
* @brief Receives SMBus transaction (out-of-band) packet from eSPI bus.
|
|
*
|
|
* This routines provides an interface to receive and decoded a SMBus
|
|
* transaction from eSPI bus
|
|
*
|
|
* @param dev Pointer to the device structure for the driver instance.
|
|
* @param pckt Address of the packet representation of SMBus transaction.
|
|
*
|
|
* @retval -EIO General input / output error, failed request to master.
|
|
*/
|
|
__syscall int espi_receive_oob(const struct device *dev,
|
|
struct espi_oob_packet *pckt);
|
|
|
|
static inline int z_impl_espi_receive_oob(const struct device *dev,
|
|
struct espi_oob_packet *pckt)
|
|
{
|
|
const struct espi_driver_api *api =
|
|
(const struct espi_driver_api *)dev->api;
|
|
|
|
if (!api->receive_oob) {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
return api->receive_oob(dev, pckt);
|
|
}
|
|
|
|
/**
|
|
* @brief Sends a read request packet for shared flash.
|
|
*
|
|
* This routines provides an interface to send a request to read the flash
|
|
* component shared between the eSPI master and eSPI slaves.
|
|
*
|
|
* @param dev Pointer to the device structure for the driver instance.
|
|
* @param pckt Adddress of the representation of read flash transaction.
|
|
*
|
|
* @retval -ENOTSUP eSPI flash logical channel transactions not supported.
|
|
* @retval -EBUSY eSPI flash channel is not ready or disabled by master.
|
|
* @retval -EIO General input / output error, failed request to master.
|
|
*/
|
|
__syscall int espi_read_flash(const struct device *dev,
|
|
struct espi_flash_packet *pckt);
|
|
|
|
static inline int z_impl_espi_read_flash(const struct device *dev,
|
|
struct espi_flash_packet *pckt)
|
|
{
|
|
const struct espi_driver_api *api =
|
|
(const struct espi_driver_api *)dev->api;
|
|
|
|
if (!api->flash_read) {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
return api->flash_read(dev, pckt);
|
|
}
|
|
|
|
/**
|
|
* @brief Sends a write request packet for shared flash.
|
|
*
|
|
* This routines provides an interface to send a request to write to the flash
|
|
* components shared between the eSPI master and eSPI slaves.
|
|
*
|
|
* @param dev Pointer to the device structure for the driver instance.
|
|
* @param pckt Address of the representation of write flash transaction.
|
|
*
|
|
* @retval -ENOTSUP eSPI flash logical channel transactions not supported.
|
|
* @retval -EBUSY eSPI flash channel is not ready or disabled by master.
|
|
* @retval -EIO General input / output error, failed request to master.
|
|
*/
|
|
__syscall int espi_write_flash(const struct device *dev,
|
|
struct espi_flash_packet *pckt);
|
|
|
|
static inline int z_impl_espi_write_flash(const struct device *dev,
|
|
struct espi_flash_packet *pckt)
|
|
{
|
|
const struct espi_driver_api *api =
|
|
(const struct espi_driver_api *)dev->api;
|
|
|
|
if (!api->flash_write) {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
return api->flash_write(dev, pckt);
|
|
}
|
|
|
|
/**
|
|
* @brief Sends a write request packet for shared flash.
|
|
*
|
|
* This routines provides an interface to send a request to write to the flash
|
|
* components shared between the eSPI master and eSPI slaves.
|
|
*
|
|
* @param dev Pointer to the device structure for the driver instance.
|
|
* @param pckt Address of the representation of write flash transaction.
|
|
*
|
|
* @retval -ENOTSUP eSPI flash logical channel transactions not supported.
|
|
* @retval -EBUSY eSPI flash channel is not ready or disabled by master.
|
|
* @retval -EIO General input / output error, failed request to master.
|
|
*/
|
|
__syscall int espi_flash_erase(const struct device *dev,
|
|
struct espi_flash_packet *pckt);
|
|
|
|
static inline int z_impl_espi_flash_erase(const struct device *dev,
|
|
struct espi_flash_packet *pckt)
|
|
{
|
|
const struct espi_driver_api *api =
|
|
(const struct espi_driver_api *)dev->api;
|
|
|
|
if (!api->flash_erase) {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
return api->flash_erase(dev, pckt);
|
|
}
|
|
|
|
/**
|
|
* Callback model
|
|
*
|
|
*+-------+ +-------------+ +------+ +---------+
|
|
*| App | | eSPI driver | | HW | |eSPI Host|
|
|
*+---+---+ +-------+-----+ +---+--+ +----+----+
|
|
* | | | |
|
|
* | espi_init_callback | | |
|
|
* +----------------------------> | | |
|
|
* | espi_add_callback | |
|
|
* +----------------------------->+ |
|
|
* | | | eSPI reset | eSPI host
|
|
* | | IRQ +<------------+ resets the
|
|
* | | <-----------+ | bus
|
|
* | | | |
|
|
* | | Processed | |
|
|
* | | within the | |
|
|
* | | driver | |
|
|
* | | | |
|
|
|
|
* | | | VW CH ready| eSPI host
|
|
* | | IRQ +<------------+ enables VW
|
|
* | | <-----------+ | channel
|
|
* | | | |
|
|
* | | Processed | |
|
|
* | | within the | |
|
|
* | | driver | |
|
|
* | | | |
|
|
* | | | Memory I/O | Peripheral
|
|
* | | <-------------+ event
|
|
* | +<------------+ |
|
|
* +<-----------------------------+ callback | |
|
|
* | Report peripheral event | | |
|
|
* | and data for the event | | |
|
|
* | | | |
|
|
* | | | SLP_S5 | eSPI host
|
|
* | | <-------------+ send VWire
|
|
* | +<------------+ |
|
|
* +<-----------------------------+ callback | |
|
|
* | App enables/configures | | |
|
|
* | discrete regulator | | |
|
|
* | | | |
|
|
* | espi_send_vwire_signal | | |
|
|
* +------------------------------>------------>|------------>|
|
|
* | | | |
|
|
* | | | HOST_RST | eSPI host
|
|
* | | <-------------+ send VWire
|
|
* | +<------------+ |
|
|
* +<-----------------------------+ callback | |
|
|
* | App reset host-related | | |
|
|
* | data structures | | |
|
|
* | | | |
|
|
* | | | C10 | eSPI host
|
|
* | | +<------------+ send VWire
|
|
* | <-------------+ |
|
|
* <------------------------------+ | |
|
|
* | App executes | | |
|
|
* + power mgmt policy | | |
|
|
*/
|
|
|
|
/**
|
|
* @brief Helper to initialize a struct espi_callback properly.
|
|
*
|
|
* @param callback A valid Application's callback structure pointer.
|
|
* @param handler A valid handler function pointer.
|
|
* @param evt_type indicates the eSPI event relevant for the handler.
|
|
* for VWIRE_RECEIVED event the data will indicate the new level asserted
|
|
*/
|
|
static inline void espi_init_callback(struct espi_callback *callback,
|
|
espi_callback_handler_t handler,
|
|
enum espi_bus_event evt_type)
|
|
{
|
|
__ASSERT(callback, "Callback pointer should not be NULL");
|
|
__ASSERT(handler, "Callback handler pointer should not be NULL");
|
|
|
|
callback->handler = handler;
|
|
callback->evt_type = evt_type;
|
|
}
|
|
|
|
/**
|
|
* @brief Add an application callback.
|
|
* @param dev Pointer to the device structure for the driver instance.
|
|
* @param callback A valid Application's callback structure pointer.
|
|
* @return 0 if successful, negative errno code on failure.
|
|
*
|
|
* @note Callbacks may be added to the device from within a callback
|
|
* handler invocation, but whether they are invoked for the current
|
|
* eSPI event is not specified.
|
|
*
|
|
* Note: enables to add as many callback as needed on the same device.
|
|
*/
|
|
static inline int espi_add_callback(const struct device *dev,
|
|
struct espi_callback *callback)
|
|
{
|
|
const struct espi_driver_api *api =
|
|
(const struct espi_driver_api *)dev->api;
|
|
|
|
if (!api->manage_callback) {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
return api->manage_callback(dev, callback, true);
|
|
}
|
|
|
|
/**
|
|
* @brief Remove an application callback.
|
|
* @param dev Pointer to the device structure for the driver instance.
|
|
* @param callback A valid application's callback structure pointer.
|
|
* @return 0 if successful, negative errno code on failure.
|
|
*
|
|
* @warning It is explicitly permitted, within a callback handler, to
|
|
* remove the registration for the callback that is running, i.e. @p
|
|
* callback. Attempts to remove other registrations on the same
|
|
* device may result in undefined behavior, including failure to
|
|
* invoke callbacks that remain registered and unintended invocation
|
|
* of removed callbacks.
|
|
*
|
|
* Note: enables to remove as many callbacks as added through
|
|
* espi_add_callback().
|
|
*/
|
|
static inline int espi_remove_callback(const struct device *dev,
|
|
struct espi_callback *callback)
|
|
{
|
|
const struct espi_driver_api *api =
|
|
(const struct espi_driver_api *)dev->api;
|
|
|
|
if (!api->manage_callback) {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
return api->manage_callback(dev, callback, false);
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
#include <syscalls/espi.h>
|
|
#endif /* ZEPHYR_INCLUDE_ESPI_H_ */
|