/* * Copyright (c) 2019 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief Public APIs for eSPI driver */ #ifndef ZEPHYR_INCLUDE_ESPI_SAF_H_ #define ZEPHYR_INCLUDE_ESPI_SAF_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /** * @brief eSPI SAF Driver APIs * @defgroup espi_interface ESPI Driver APIs * @ingroup io_interfaces * @{ */ /** * @code *+----------------------------------------------------------------------+ *| | *| eSPI host +-------------+ | *| +-----------+ | Power | +----------+ | *| |Out of band| | management | | GPIO | | *| ------------ |processor | | controller | | sources | | *| +-----------+ +-------------+ +----------+ | *| | | | | *| ------------ | | | | *| +--------+ +---------------+ | *| | | | *| -----+ +--------+ +----------+ +----v-----+ | *| | | LPC | | Tunneled | | Tunneled | | *| | | bridge | | SMBus | | GPIO | | *| | +--------+ +----------+ +----------+ | *| | | | | | *| | ------+ | | | *| | | | | | *| +------v-----+ +---v-------v-------------v----+ | *| | eSPI Flash | | eSPI protocol block | | *| | access +--->+ | | *| +------------+ +------------------------------+ | *| | | *| ----------- | | *| v | *| XXXXXXXXXXXXXXXXXXXXXXX | *| XXXXXXXXXXXXXXXXXXXXX | *| XXXXXXXXXXXXXXXXXXX | *+----------------------------------------------------------------------+ * | * +-----------------+ * --------- | | | | | | * | | | | | | * --------- | + + + + | eSPI bus * | CH0 CH1 CH2 CH3 | (logical channels) * | + + + + | * | | | | | | * +-----------------+ * | *+-----------------------------------------------------------------------+ *| eSPI slave | *| | *| CH0 | CH1 | CH2 | CH3 | *| eSPI endpoint | VWIRE | OOB | Flash | *+-----------------------------------------------------------------------+ * | | * v | * +---------+ | * | Flash | Slave Attached Flash | * +---------+ | * | * @endcode */ /** * @cond INTERNAL_HIDDEN * */ /** @endcond */ struct espi_saf_hw_cfg; struct espi_saf_flash_cfg; struct espi_saf_pr; /** * @brief eSPI SAF configuration parameters */ struct espi_saf_cfg { uint8_t nflash_devices; struct espi_saf_hw_cfg hwcfg; struct espi_saf_flash_cfg *flash_cfgs; }; /** * @brief eSPI SAF transaction packet format */ struct espi_saf_packet { uint32_t flash_addr; uint8_t *buf; uint32_t len; }; /* *defined in espi.h * struct espi_callback * typedef void (*espi_callback_handler_t)() */ /** * @cond INTERNAL_HIDDEN * * eSPI driver API definition and system call entry points * * (Internal use only.) */ typedef int (*espi_saf_api_config)(const struct device *dev, const struct espi_saf_cfg *cfg); typedef int (*espi_saf_api_set_protection_regions)( const struct device *dev, const struct espi_saf_protection *pr); typedef int (*espi_saf_api_activate)(const struct device *dev); typedef bool (*espi_saf_api_get_channel_status)(const struct device *dev); typedef int (*espi_saf_api_flash_read)(const struct device *dev, struct espi_saf_packet *pckt); typedef int (*espi_saf_api_flash_write)(const struct device *dev, struct espi_saf_packet *pckt); typedef int (*espi_saf_api_flash_erase)(const struct device *dev, struct espi_saf_packet *pckt); typedef int (*espi_saf_api_flash_unsuccess)(const struct device *dev, struct espi_saf_packet *pckt); /* Callbacks and traffic intercept */ typedef int (*espi_saf_api_manage_callback)(const struct device *dev, struct espi_callback *callback, bool set); __subsystem struct espi_saf_driver_api { espi_saf_api_config config; espi_saf_api_set_protection_regions set_protection_regions; espi_saf_api_activate activate; espi_saf_api_get_channel_status get_channel_status; espi_saf_api_flash_read flash_read; espi_saf_api_flash_write flash_write; espi_saf_api_flash_erase flash_erase; espi_saf_api_flash_unsuccess flash_unsuccess; espi_saf_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. * * @code * +--------+ +---------+ +------+ +---------+ +---------+ * | 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 | | * | | +------------------>+ | * + + + + + * @endcode * * @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_saf_config(const struct device *dev, const struct espi_saf_cfg *cfg); static inline int z_impl_espi_saf_config(const struct device *dev, const struct espi_saf_cfg *cfg) { const struct espi_saf_driver_api *api = (const struct espi_saf_driver_api *)dev->api; return api->config(dev, cfg); } /** * @brief Set one or more SAF protection regions * * This routine provides an interface to override the default flash * protection regions of the SAF controller. * * @param dev Pointer to the device structure for the driver instance. * @param pr Pointer to the SAF protection region structure. * * @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_saf_set_protection_regions( const struct device *dev, const struct espi_saf_protection *pr); static inline int z_impl_espi_saf_set_protection_regions( const struct device *dev, const struct espi_saf_protection *pr) { const struct espi_saf_driver_api *api = (const struct espi_saf_driver_api *)dev->api; return api->set_protection_regions(dev, pr); } /** * @brief Activate SAF block * * This routine activates the SAF block and should only be * called after SAF has been configured and the eSPI Master * has enabled the Flash Channel. * * @param dev Pointer to the device structure for the driver instance. * * @retval 0 If successful * @retval -EINVAL if failed to activate SAF. */ __syscall int espi_saf_activate(const struct device *dev); static inline int z_impl_espi_saf_activate(const struct device *dev) { const struct espi_saf_driver_api *api = (const struct espi_saf_driver_api *)dev->api; return api->activate(dev); } /** * @brief Query to see if SAF is ready * * This routine allows to check if SAF is ready before use. * * @param dev Pointer to the device structure for the driver instance. * * @retval true If eSPI SAF is ready. * @retval false otherwise. */ __syscall bool espi_saf_get_channel_status(const struct device *dev); static inline bool z_impl_espi_saf_get_channel_status( const struct device *dev) { const struct espi_saf_driver_api *api = (const struct espi_saf_driver_api *)dev->api; return api->get_channel_status(dev); } /** * @brief Sends a read request packet for slave attached 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 Address 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_saf_flash_read(const struct device *dev, struct espi_saf_packet *pckt); static inline int z_impl_espi_saf_flash_read(const struct device *dev, struct espi_saf_packet *pckt) { const struct espi_saf_driver_api *api = (const struct espi_saf_driver_api *)dev->api; if (!api->flash_read) { return -ENOTSUP; } return api->flash_read(dev, pckt); } /** * @brief Sends a write request packet for slave attached 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_saf_flash_write(const struct device *dev, struct espi_saf_packet *pckt); static inline int z_impl_espi_saf_flash_write(const struct device *dev, struct espi_saf_packet *pckt) { const struct espi_saf_driver_api *api = (const struct espi_saf_driver_api *)dev->api; if (!api->flash_write) { return -ENOTSUP; } return api->flash_write(dev, pckt); } /** * @brief Sends a write request packet for slave attached 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 erase 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_saf_flash_erase(const struct device *dev, struct espi_saf_packet *pckt); static inline int z_impl_espi_saf_flash_erase(const struct device *dev, struct espi_saf_packet *pckt) { const struct espi_saf_driver_api *api = (const struct espi_saf_driver_api *)dev->api; if (!api->flash_erase) { return -ENOTSUP; } return api->flash_erase(dev, pckt); } /** * @brief Response unsuccessful completion for slave attached flash. * * This routines provides an interface to response that transaction is * invalid and return unsuccessful completion from target to controller. * * @param dev Pointer to the device structure for the driver instance. * @param pckt Address of the representation of 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_saf_flash_unsuccess(const struct device *dev, struct espi_saf_packet *pckt); static inline int z_impl_espi_saf_flash_unsuccess(const struct device *dev, struct espi_saf_packet *pckt) { const struct espi_saf_driver_api *api = (const struct espi_saf_driver_api *)dev->api; if (!api->flash_unsuccess) { return -ENOTSUP; } return api->flash_unsuccess(dev, pckt); } /** * Callback model * * @code *+-------+ +-------------+ +------+ +---------+ *| 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 | | | * @endcode */ /** * @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_saf_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_saf_add_callback(const struct device *dev, struct espi_callback *callback) { const struct espi_saf_driver_api *api = (const struct espi_saf_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_saf_remove_callback(const struct device *dev, struct espi_callback *callback) { const struct espi_saf_driver_api *api = (const struct espi_saf_driver_api *)dev->api; if (!api->manage_callback) { return -ENOTSUP; } return api->manage_callback(dev, callback, false); } #ifdef __cplusplus } #endif /** * @} */ #include #endif /* ZEPHYR_INCLUDE_ESPI_SAF_H_ */