drivers: can: add API for getting supported capabilities

Add API function for getting the supported capabilities of a CAN
controller. This allows for writing portable CAN applications.

Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
Henrik Brix Andersen 2022-07-12 16:36:20 +02:00 committed by Carles Cufí
commit bb08e4251a
13 changed files with 107 additions and 0 deletions

View file

@ -138,6 +138,15 @@ static inline int z_vrfy_can_get_max_filters(const struct device *dev, enum can_
}
#include <syscalls/can_get_max_filters_mrsh.c>
static inline int z_vrfy_can_get_capabilities(const struct device *dev, can_mode_t *cap)
{
Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, get_capabilities));
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(cap, sizeof(*cap)));
return z_impl_can_get_capabilities(dev, cap);
}
#include <syscalls/can_get_capabilities_mrsh.c>
static inline int z_vrfy_can_set_mode(const struct device *dev, can_mode_t mode)
{
Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, set_mode));

View file

@ -197,6 +197,15 @@ static void can_loopback_remove_rx_filter(const struct device *dev, int filter_i
k_mutex_unlock(&data->mtx);
}
static int can_loopback_get_capabilities(const struct device *dev, can_mode_t *cap)
{
ARG_UNUSED(dev);
*cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK;
return 0;
}
static int can_loopback_set_mode(const struct device *dev, can_mode_t mode)
{
struct can_loopback_data *data = dev->data;
@ -265,6 +274,7 @@ static int can_loopback_get_max_filters(const struct device *dev, enum can_ide i
}
static const struct can_driver_api can_loopback_driver_api = {
.get_capabilities = can_loopback_get_capabilities,
.set_mode = can_loopback_set_mode,
.set_timing = can_loopback_set_timing,
.send = can_loopback_send,

View file

@ -240,6 +240,19 @@ int can_mcan_set_timing_data(const struct device *dev,
}
#endif /* CONFIG_CAN_FD_MODE */
int can_mcan_get_capabilities(const struct device *dev, can_mode_t *cap)
{
ARG_UNUSED(dev);
*cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY;
#if CONFIG_CAN_FD_MODE
*cap |= CAN_MODE_FD;
#endif /* CONFIG_CAN_FD_MODE */
return 0;
}
int can_mcan_set_mode(const struct device *dev, can_mode_t mode)
{
const struct can_mcan_config *cfg = dev->config;

View file

@ -257,6 +257,8 @@ struct can_mcan_reg;
.custom = _custom_data, \
}
int can_mcan_get_capabilities(const struct device *dev, can_mode_t *cap);
int can_mcan_set_mode(const struct device *dev, can_mode_t mode);
int can_mcan_set_timing(const struct device *dev,

View file

@ -440,6 +440,15 @@ done:
return ret;
}
static int mcp2515_get_capabilities(const struct device *dev, can_mode_t *cap)
{
ARG_UNUSED(dev);
*cap = CAN_MODE_NORMAL | CAN_MODE_LISTENONLY | CAN_MODE_LOOPBACK;
return 0;
}
static int mcp2515_set_mode(const struct device *dev, can_mode_t mode)
{
const struct mcp2515_config *dev_cfg = dev->config;
@ -827,6 +836,7 @@ static void mcp2515_int_gpio_callback(const struct device *dev,
}
static const struct can_driver_api can_api_funcs = {
.get_capabilities = mcp2515_get_capabilities,
.set_timing = mcp2515_set_timing,
.set_mode = mcp2515_set_mode,
.send = mcp2515_send,

View file

@ -179,6 +179,15 @@ static int mcux_flexcan_set_timing(const struct device *dev,
return 0;
}
static int mcux_flexcan_get_capabilities(const struct device *dev, can_mode_t *cap)
{
ARG_UNUSED(dev);
*cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY;
return 0;
}
static int mcux_flexcan_set_mode(const struct device *dev, can_mode_t mode)
{
const struct mcux_flexcan_config *config = dev->config;
@ -783,6 +792,7 @@ static int mcux_flexcan_init(const struct device *dev)
}
static const struct can_driver_api mcux_flexcan_driver_api = {
.get_capabilities = mcux_flexcan_get_capabilities,
.set_mode = mcux_flexcan_set_mode,
.set_timing = mcux_flexcan_set_timing,
.send = mcux_flexcan_send,

View file

@ -58,6 +58,7 @@ static int mcux_mcan_init(const struct device *dev)
}
static const struct can_driver_api mcux_mcan_driver_api = {
.get_capabilities = can_mcan_get_capabilities,
.set_mode = can_mcan_set_mode,
.set_timing = can_mcan_set_timing,
.send = can_mcan_send,

View file

@ -571,6 +571,15 @@ static int can_rcar_enter_operation_mode(const struct can_rcar_cfg *config)
return 0;
}
static int can_rcar_get_capabilities(const struct device *dev, can_mode_t *cap)
{
ARG_UNUSED(dev);
*cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY;
return 0;
}
static int can_rcar_set_mode(const struct device *dev, can_mode_t mode)
{
const struct can_rcar_cfg *config = dev->config;
@ -1072,6 +1081,7 @@ static int can_rcar_get_max_bitrate(const struct device *dev, uint32_t *max_bitr
}
static const struct can_driver_api can_rcar_driver_api = {
.get_capabilities = can_rcar_get_capabilities,
.set_mode = can_rcar_set_mode,
.set_timing = can_rcar_set_timing,
.send = can_rcar_send,

View file

@ -70,6 +70,7 @@ static int can_sam_init(const struct device *dev)
}
static const struct can_driver_api can_sam_driver_api = {
.get_capabilities = can_mcan_get_capabilities,
.set_mode = can_mcan_set_mode,
.set_timing = can_mcan_set_timing,
.send = can_mcan_send,

View file

@ -342,6 +342,15 @@ static int can_leave_sleep_mode(CAN_TypeDef *can)
return 0;
}
static int can_stm32_get_capabilities(const struct device *dev, can_mode_t *cap)
{
ARG_UNUSED(dev);
*cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY;
return 0;
}
static int can_stm32_set_mode(const struct device *dev, can_mode_t mode)
{
const struct can_stm32_config *cfg = dev->config;
@ -1126,6 +1135,7 @@ static void can_stm32_remove_rx_filter(const struct device *dev, int filter_id)
}
static const struct can_driver_api can_api_funcs = {
.get_capabilities = can_stm32_get_capabilities,
.set_mode = can_stm32_set_mode,
.set_timing = can_stm32_set_timing,
.send = can_stm32_send,

View file

@ -123,6 +123,7 @@ static int can_stm32fd_init(const struct device *dev)
}
static const struct can_driver_api can_stm32fd_driver_api = {
.get_capabilities = can_mcan_get_capabilities,
.set_mode = can_mcan_set_mode,
.set_timing = can_mcan_set_timing,
.send = can_mcan_send,

View file

@ -95,6 +95,7 @@ static int can_stm32h7_init(const struct device *dev)
}
static const struct can_driver_api can_stm32h7_driver_api = {
.get_capabilities = can_mcan_get_capabilities,
.set_mode = can_mcan_set_mode,
.set_timing = can_mcan_set_timing,
.send = can_mcan_send,

View file

@ -326,6 +326,12 @@ typedef int (*can_set_timing_t)(const struct device *dev,
typedef int (*can_set_timing_data_t)(const struct device *dev,
const struct can_timing *timing_data);
/**
* @brief Callback API upon getting CAN controller capabilities
* See @a can_get_capabilities() for argument description
*/
typedef int (*can_get_capabilities_t)(const struct device *dev, can_mode_t *cap);
/**
* @brief Callback API upon setting CAN controller mode
* See @a can_set_mode() for argument description
@ -396,6 +402,7 @@ typedef int (*can_get_max_filters_t)(const struct device *dev, enum can_ide id_t
typedef int (*can_get_max_bitrate_t)(const struct device *dev, uint32_t *max_bitrate);
__subsystem struct can_driver_api {
can_get_capabilities_t get_capabilities;
can_set_mode_t set_mode;
can_set_timing_t set_timing;
can_send_t send;
@ -902,6 +909,28 @@ static inline int z_impl_can_set_timing(const struct device *dev,
return api->set_timing(dev, timing);
}
/**
* @brief Get the supported modes of the CAN controller
*
* The returned capabilities may not necessarily be supported at the same time (e.g. some CAN
* controllers support both ``CAN_MODE_LOOPBACK`` and ``CAN_MODE_LISTENONLY``, but not at the same
* time).
*
* @param dev Pointer to the device structure for the driver instance.
* @param[out] cap Supported capabilities.
*
* @retval 0 If successful.
* @retval -EIO General input/output error, failed to get capabilities.
*/
__syscall int can_get_capabilities(const struct device *dev, can_mode_t *cap);
static inline int z_impl_can_get_capabilities(const struct device *dev, can_mode_t *cap)
{
const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
return api->get_capabilities(dev, cap);
}
/**
* @brief Set the CAN controller to the given operation mode
*