drivers: can: loopback: add CAN-FD loopback support

Add support for CAN-FD frames in the CAN loopback driver.

Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
Henrik Brix Andersen 2022-07-18 13:23:17 +02:00 committed by Carles Cufí
parent 4b30008f5b
commit b407b5697f
2 changed files with 56 additions and 4 deletions

View file

@ -7,6 +7,7 @@ DT_COMPAT_ZEPHYR_CAN_LOOPBACK := zephyr,can-loopback
config CAN_LOOPBACK
bool "Emulated CAN loopback driver"
select CAN_HAS_CANFD
default $(dt_compat_enabled,$(DT_COMPAT_ZEPHYR_CAN_LOOPBACK))
help
This is an emulated driver that can only loopback messages.

View file

@ -96,9 +96,10 @@ static int can_loopback_send(const struct device *dev,
void *user_data)
{
struct can_loopback_data *data = dev->data;
int ret;
struct can_loopback_frame loopback_frame;
uint8_t max_dlc = CAN_MAX_DLC;
struct k_sem tx_sem;
int ret;
LOG_DBG("Sending %d bytes on %s. Id: 0x%x, ID type: %s %s",
frame->dlc, dev->name, frame->id,
@ -106,8 +107,14 @@ static int can_loopback_send(const struct device *dev,
"standard" : "extended",
frame->rtr == CAN_DATAFRAME ? "" : ", RTR frame");
if (frame->dlc > CAN_MAX_DLC) {
LOG_ERR("DLC of %d exceeds maximum (%d)", frame->dlc, CAN_MAX_DLC);
#ifdef CONFIG_CAN_FD_MODE
if (frame->fd != 0) {
max_dlc = CANFD_MAX_DLC;
}
#endif /* CONFIG_CAN_FD_MODE */
if (frame->dlc > max_dlc) {
LOG_ERR("DLC of %d exceeds maximum (%d)", frame->dlc, max_dlc);
return -EINVAL;
}
@ -198,6 +205,10 @@ static int can_loopback_get_capabilities(const struct device *dev, can_mode_t *c
*cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK;
#if CONFIG_CAN_FD_MODE
*cap |= CAN_MODE_FD;
#endif /* CONFIG_CAN_FD_MODE */
return 0;
}
@ -205,6 +216,18 @@ static int can_loopback_set_mode(const struct device *dev, can_mode_t mode)
{
struct can_loopback_data *data = dev->data;
#ifdef CONFIG_CAN_FD_MODE
if ((mode & ~(CAN_MODE_LOOPBACK | CAN_MODE_FD)) != 0) {
LOG_ERR("unsupported mode: 0x%08x", mode);
return -ENOTSUP;
}
#else
if ((mode & ~(CAN_MODE_LOOPBACK)) != 0) {
LOG_ERR("unsupported mode: 0x%08x", mode);
return -ENOTSUP;
}
#endif /* CONFIG_CAN_FD_MODE */
data->loopback = (mode & CAN_MODE_LOOPBACK) != 0 ? 1 : 0;
return 0;
}
@ -218,6 +241,17 @@ static int can_loopback_set_timing(const struct device *dev,
return 0;
}
#ifdef CONFIG_CAN_FD_MODE
static int can_loopback_set_timing_data(const struct device *dev,
const struct can_timing *timing)
{
ARG_UNUSED(dev);
ARG_UNUSED(timing);
return 0;
}
#endif /* CONFIG_CAN_FD_MODE */
static int can_loopback_get_state(const struct device *dev, enum can_state *state,
struct can_bus_err_cnt *err_cnt)
{
@ -295,7 +329,24 @@ static const struct can_driver_api can_loopback_driver_api = {
.phase_seg1 = 0x0F,
.phase_seg2 = 0x0F,
.prescaler = 0xFFFF
}
},
#ifdef CONFIG_CAN_FD_MODE
.set_timing_data = can_loopback_set_timing_data,
.timing_data_min = {
.sjw = 0x1,
.prop_seg = 0x01,
.phase_seg1 = 0x01,
.phase_seg2 = 0x01,
.prescaler = 0x01
},
.timing_data_max = {
.sjw = 0x0F,
.prop_seg = 0x0F,
.phase_seg1 = 0x0F,
.phase_seg2 = 0x0F,
.prescaler = 0xFFFF
},
#endif /* CONFIG_CAN_FD_MODE */
};
static int can_loopback_init(const struct device *dev)