smbus: Add Host Notify and smbalert API
Add API for SMBus Host Notify and SMBALERT. Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
This commit is contained in:
parent
2de1936acc
commit
2146b19cc7
3 changed files with 205 additions and 1 deletions
|
@ -4,8 +4,9 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <zephyr/drivers/smbus.h>
|
#include <zephyr/sys/slist.h>
|
||||||
#include <zephyr/syscall_handler.h>
|
#include <zephyr/syscall_handler.h>
|
||||||
|
#include <zephyr/drivers/smbus.h>
|
||||||
|
|
||||||
static inline int z_vrfy_smbus_configure(const struct device *dev,
|
static inline int z_vrfy_smbus_configure(const struct device *dev,
|
||||||
uint32_t dev_config)
|
uint32_t dev_config)
|
||||||
|
@ -142,3 +143,23 @@ static inline int z_vrfy_smbus_block_pcall(const struct device *dev,
|
||||||
rcv_count, rcv_buf);
|
rcv_count, rcv_buf);
|
||||||
}
|
}
|
||||||
#include <syscalls/smbus_block_pcall_mrsh.c>
|
#include <syscalls/smbus_block_pcall_mrsh.c>
|
||||||
|
|
||||||
|
static inline int z_vrfy_smbus_manage_smbalert_cb(const struct device *dev,
|
||||||
|
struct smbus_callback *cb,
|
||||||
|
bool set)
|
||||||
|
{
|
||||||
|
Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS));
|
||||||
|
|
||||||
|
return z_impl_smbus_manage_smbalert_cb(dev, cb, set);
|
||||||
|
}
|
||||||
|
#include <syscalls/smbus_manage_smbalert_cb_mrsh.c>
|
||||||
|
|
||||||
|
static inline int z_vrfy_smbus_manage_host_notify_cb(const struct device *dev,
|
||||||
|
struct smbus_callback *cb,
|
||||||
|
bool set)
|
||||||
|
{
|
||||||
|
Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_SMBUS));
|
||||||
|
|
||||||
|
return z_impl_smbus_manage_host_notify_cb(dev, cb, set);
|
||||||
|
}
|
||||||
|
#include <syscalls/smbus_manage_host_notify_cb_mrsh.c>
|
||||||
|
|
|
@ -209,6 +209,12 @@ extern "C" {
|
||||||
/** Support Packet Error Code (PEC) checking */
|
/** Support Packet Error Code (PEC) checking */
|
||||||
#define SMBUS_MODE_PEC BIT(1)
|
#define SMBUS_MODE_PEC BIT(1)
|
||||||
|
|
||||||
|
/** Support Host Notify functionality */
|
||||||
|
#define SMBUS_MODE_HOST_NOTIFY BIT(2)
|
||||||
|
|
||||||
|
/** Support SMBALERT signal functionality */
|
||||||
|
#define SMBUS_MODE_SMBALERT BIT(3)
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -247,6 +253,32 @@ enum smbus_direction {
|
||||||
#define SMBUS_MSG_RW_MASK BIT(0)
|
#define SMBUS_MSG_RW_MASK BIT(0)
|
||||||
/** @endcond */
|
/** @endcond */
|
||||||
|
|
||||||
|
struct smbus_callback;
|
||||||
|
|
||||||
|
typedef void (*smbus_callback_handler_t)(const struct device *dev,
|
||||||
|
struct smbus_callback *cb,
|
||||||
|
uint8_t addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SMBus callback structure
|
||||||
|
*
|
||||||
|
* 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 smbus_callback.
|
||||||
|
*
|
||||||
|
* Note: Such struct should not be allocated on stack.
|
||||||
|
*/
|
||||||
|
struct smbus_callback {
|
||||||
|
/** This should be used in driver for a callback list management */
|
||||||
|
sys_snode_t node;
|
||||||
|
|
||||||
|
/** Actual callback function being called when relevant */
|
||||||
|
smbus_callback_handler_t handler;
|
||||||
|
|
||||||
|
/** Peripheral device address */
|
||||||
|
uint8_t addr;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Complete SMBus DT information
|
* @brief Complete SMBus DT information
|
||||||
*
|
*
|
||||||
|
@ -326,6 +358,12 @@ typedef int (*smbus_api_block_pcall_t)(const struct device *dev,
|
||||||
uint16_t addr, uint8_t cmd,
|
uint16_t addr, uint8_t cmd,
|
||||||
uint8_t send_count, uint8_t *send_buf,
|
uint8_t send_count, uint8_t *send_buf,
|
||||||
uint8_t *recv_count, uint8_t *recv_buf);
|
uint8_t *recv_count, uint8_t *recv_buf);
|
||||||
|
typedef int (*smbus_api_manage_smbalert_cb_t)(const struct device *dev,
|
||||||
|
struct smbus_callback *cb,
|
||||||
|
bool set);
|
||||||
|
typedef int (*smbus_api_manage_host_notify_cb_t)(const struct device *dev,
|
||||||
|
struct smbus_callback *cb,
|
||||||
|
bool set);
|
||||||
|
|
||||||
__subsystem struct smbus_driver_api {
|
__subsystem struct smbus_driver_api {
|
||||||
smbus_api_configure_t configure;
|
smbus_api_configure_t configure;
|
||||||
|
@ -341,6 +379,8 @@ __subsystem struct smbus_driver_api {
|
||||||
smbus_api_block_write_t smbus_block_write;
|
smbus_api_block_write_t smbus_block_write;
|
||||||
smbus_api_block_read_t smbus_block_read;
|
smbus_api_block_read_t smbus_block_read;
|
||||||
smbus_api_block_pcall_t smbus_block_pcall;
|
smbus_api_block_pcall_t smbus_block_pcall;
|
||||||
|
smbus_api_manage_smbalert_cb_t smbus_manage_smbalert_cb;
|
||||||
|
smbus_api_manage_host_notify_cb_t smbus_manage_host_notify_cb;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -547,6 +587,64 @@ static inline int z_impl_smbus_get_config(const struct device *dev,
|
||||||
return api->get_config(dev, dev_config);
|
return api->get_config(dev, dev_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add SMBUSALERT callback for a SMBus host controller.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param cb Pointer to a callback structure.
|
||||||
|
* @param set A boolean indicating insertion or removal of the callback.
|
||||||
|
*
|
||||||
|
* @retval 0 If successful.
|
||||||
|
* @retval -EIO General input / output error, failed to configure device.
|
||||||
|
* @retval -ENOSYS If get config is not implemented
|
||||||
|
*/
|
||||||
|
__syscall int smbus_manage_smbalert_cb(const struct device *dev,
|
||||||
|
struct smbus_callback *cb,
|
||||||
|
bool set);
|
||||||
|
|
||||||
|
static inline int z_impl_smbus_manage_smbalert_cb(const struct device *dev,
|
||||||
|
struct smbus_callback *cb,
|
||||||
|
bool set)
|
||||||
|
{
|
||||||
|
const struct smbus_driver_api *api =
|
||||||
|
(const struct smbus_driver_api *)dev->api;
|
||||||
|
|
||||||
|
if (api->smbus_manage_smbalert_cb == NULL) {
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return api->smbus_manage_smbalert_cb(dev, cb, set);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add Host Notify callback for a SMBus host controller.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param cb Pointer to a callback structure.
|
||||||
|
* @param set A boolean indicating insertion or removal of the callback.
|
||||||
|
*
|
||||||
|
* @retval 0 If successful.
|
||||||
|
* @retval -EIO General input / output error, failed to configure device.
|
||||||
|
* @retval -ENOSYS If get config is not implemented
|
||||||
|
*/
|
||||||
|
__syscall int smbus_manage_host_notify_cb(const struct device *dev,
|
||||||
|
struct smbus_callback *cb,
|
||||||
|
bool set);
|
||||||
|
|
||||||
|
static inline int z_impl_smbus_manage_host_notify_cb(const struct device *dev,
|
||||||
|
struct smbus_callback *cb,
|
||||||
|
bool set)
|
||||||
|
{
|
||||||
|
const struct smbus_driver_api *api =
|
||||||
|
(const struct smbus_driver_api *)dev->api;
|
||||||
|
|
||||||
|
if (api->smbus_manage_host_notify_cb == NULL) {
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return api->smbus_manage_host_notify_cb(dev, cb, set);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Perform SMBus Quick operation
|
* @brief Perform SMBus Quick operation
|
||||||
*
|
*
|
||||||
|
|
85
include/zephyr/drivers/smbus_utils.h
Normal file
85
include/zephyr/drivers/smbus_utils.h
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_DRIVERS_SMBUS_SMBUS_UTILS_H_
|
||||||
|
#define ZEPHYR_DRIVERS_SMBUS_SMBUS_UTILS_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generic function to insert or remove a callback from a callback list
|
||||||
|
*
|
||||||
|
* @param callbacks A pointer to the original list of callbacks (can be NULL)
|
||||||
|
* @param callback A pointer of the callback to insert or remove from the list
|
||||||
|
* @param set A boolean indicating insertion or removal of the callback
|
||||||
|
*
|
||||||
|
* @return 0 on success, negative errno otherwise.
|
||||||
|
*/
|
||||||
|
static inline int smbus_manage_smbus_callback(sys_slist_t *callbacks,
|
||||||
|
struct smbus_callback *callback,
|
||||||
|
bool set)
|
||||||
|
{
|
||||||
|
__ASSERT(callback, "No callback!");
|
||||||
|
__ASSERT(callback->handler, "No callback handler!");
|
||||||
|
|
||||||
|
if (!sys_slist_is_empty(callbacks)) {
|
||||||
|
if (!sys_slist_find_and_remove(callbacks, &callback->node)) {
|
||||||
|
if (!set) {
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!set) {
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set) {
|
||||||
|
sys_slist_prepend(callbacks, &callback->node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generic function to go through and fire callback from a callback list
|
||||||
|
*
|
||||||
|
* @param list A pointer on the SMBus callback list
|
||||||
|
* @param dev A pointer on the SMBus device instance
|
||||||
|
* @param addr A SMBus peripheral device address.
|
||||||
|
*/
|
||||||
|
static inline void smbus_fire_callbacks(sys_slist_t *list,
|
||||||
|
const struct device *dev,
|
||||||
|
uint8_t addr)
|
||||||
|
{
|
||||||
|
struct smbus_callback *cb, *tmp;
|
||||||
|
|
||||||
|
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(list, cb, tmp, node) {
|
||||||
|
if (cb->addr == addr) {
|
||||||
|
__ASSERT(cb->handler, "No callback handler!");
|
||||||
|
cb->handler(dev, cb, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper to initialize a struct smbus_callback properly
|
||||||
|
*
|
||||||
|
* @param callback A valid Application's callback structure pointer.
|
||||||
|
* @param handler A valid handler function pointer.
|
||||||
|
* @param addr A SMBus peripheral device address.
|
||||||
|
*/
|
||||||
|
static inline void smbus_init_callback(struct smbus_callback *callback,
|
||||||
|
smbus_callback_handler_t handler,
|
||||||
|
uint8_t addr)
|
||||||
|
{
|
||||||
|
__ASSERT(callback, "Callback pointer should not be NULL");
|
||||||
|
__ASSERT(handler, "Callback handler pointer should not be NULL");
|
||||||
|
|
||||||
|
callback->handler = handler;
|
||||||
|
callback->addr = addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_DRIVERS_SMBUS_SMBUS_UTILS_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue