drivers: can: mcan: use per-instance message RAM configuration

Restructure the Bosch M_CAN driver backend to use per-instance Message RAM
configuration.

This removes the need for a common, artificial "can" devicetree node for
SoCs with multiple Bosch M_CAN-based CAN controllers and allows for
per-instance configuration of the number of e.g. standard (11-bit) and
extended (29-bit) filter elements.

As part of the restructure, software handling of CAN filter flags was moved
from per-flags bitfields to per-filter bitfields, solving an issue when
using more than 32 standard (11-bit) filter elements or more than 16
extended (29-bit) filter elements.

Fixes: #42030, #53417

Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
Henrik Brix Andersen 2023-05-22 16:31:09 +02:00 committed by Anas Nashif
commit 0f36f1a3ee
24 changed files with 878 additions and 546 deletions

View file

@ -342,6 +342,7 @@ int can_mcan_start(const struct device *dev)
int can_mcan_stop(const struct device *dev)
{
const struct can_mcan_config *config = dev->config;
const struct can_mcan_callbacks *cbs = config->callbacks;
struct can_mcan_data *data = dev->data;
can_tx_callback_t tx_cb;
uint32_t tx_idx;
@ -370,12 +371,12 @@ int can_mcan_stop(const struct device *dev)
data->started = false;
for (tx_idx = 0U; tx_idx < ARRAY_SIZE(data->tx_fin_cb); tx_idx++) {
tx_cb = data->tx_fin_cb[tx_idx];
for (tx_idx = 0U; tx_idx < cbs->num_tx; tx_idx++) {
tx_cb = cbs->tx[tx_idx].function;
if (tx_cb != NULL) {
data->tx_fin_cb[tx_idx] = NULL;
tx_cb(dev, -ENETDOWN, data->tx_fin_cb_arg[tx_idx]);
cbs->tx[tx_idx].function = NULL;
tx_cb(dev, -ENETDOWN, cbs->tx[tx_idx].user_data);
k_sem_give(&data->tx_sem);
}
}
@ -476,6 +477,8 @@ static void can_mcan_state_change_handler(const struct device *dev)
static void can_mcan_tc_event_handler(const struct device *dev)
{
const struct can_mcan_config *config = dev->config;
const struct can_mcan_callbacks *cbs = config->callbacks;
struct can_mcan_data *data = dev->data;
struct can_mcan_tx_event_fifo tx_event;
can_tx_callback_t tx_cb;
@ -491,7 +494,8 @@ static void can_mcan_tc_event_handler(const struct device *dev)
while ((txefs & CAN_MCAN_TXEFS_EFFL) != 0U) {
event_idx = FIELD_GET(CAN_MCAN_TXEFS_EFGI, txefs);
err = can_mcan_read_mram(dev, CAN_MCAN_MRAM_OFFSET_TX_EVENT_FIFO +
err = can_mcan_read_mram(dev,
config->mram_offsets[CAN_MCAN_MRAM_CFG_TX_EVENT_FIFO] +
event_idx * sizeof(struct can_mcan_tx_event_fifo),
&tx_event,
sizeof(struct can_mcan_tx_event_fifo));
@ -510,9 +514,10 @@ static void can_mcan_tc_event_handler(const struct device *dev)
k_sem_give(&data->tx_sem);
tx_cb = data->tx_fin_cb[tx_idx];
data->tx_fin_cb[tx_idx] = NULL;
tx_cb(dev, 0, data->tx_fin_cb_arg[tx_idx]);
__ASSERT_NO_MSG(tx_idx <= cbs->num_tx);
tx_cb = cbs->tx[tx_idx].function;
cbs->tx[tx_idx].function = NULL;
tx_cb(dev, 0, cbs->tx[tx_idx].user_data);
err = can_mcan_read_reg(dev, CAN_MCAN_TXEFS, &txefs);
if (err != 0) {
@ -573,16 +578,16 @@ void can_mcan_line_0_isr(const struct device *dev)
static void can_mcan_get_message(const struct device *dev, uint16_t fifo_offset,
uint16_t fifo_status_reg, uint16_t fifo_ack_reg)
{
struct can_mcan_data *data = dev->data;
uint32_t get_idx, filt_idx;
const struct can_mcan_config *config = dev->config;
const struct can_mcan_callbacks *cbs = config->callbacks;
struct can_mcan_rx_fifo_hdr hdr;
struct can_frame frame = {0};
can_rx_callback_t cb;
void *user_data;
uint8_t flags;
uint32_t get_idx;
uint32_t filt_idx;
int data_length;
void *cb_arg;
struct can_mcan_rx_fifo_hdr hdr;
bool rtr_filter_mask;
bool rtr_filter;
bool fd_frame_filter;
uint32_t fifo_status;
int err;
@ -630,25 +635,25 @@ static void can_mcan_get_message(const struct device *dev, uint16_t fifo_offset,
if (hdr.xtd != 0) {
frame.id = hdr.ext_id;
frame.flags |= CAN_FRAME_IDE;
rtr_filter_mask = (data->ext_filt_rtr_mask & BIT(filt_idx)) != 0U;
rtr_filter = (data->ext_filt_rtr & BIT(filt_idx)) != 0;
fd_frame_filter = (data->ext_filt_fd_frame & BIT(filt_idx)) != 0U;
flags = cbs->ext[filt_idx].flags;
} else {
frame.id = hdr.std_id;
rtr_filter_mask = (data->std_filt_rtr_mask & BIT(filt_idx)) != 0U;
rtr_filter = (data->std_filt_rtr & BIT(filt_idx)) != 0;
fd_frame_filter = (data->std_filt_fd_frame & BIT(filt_idx)) != 0U;
flags = cbs->std[filt_idx].flags;
}
if (rtr_filter_mask && (rtr_filter != ((frame.flags & CAN_FRAME_RTR) != 0U))) {
/* RTR bit does not match filter RTR mask, drop frame */
if (((frame.flags & CAN_FRAME_RTR) == 0U && (flags & CAN_FILTER_DATA) == 0U) ||
((frame.flags & CAN_FRAME_RTR) != 0U && (flags & CAN_FILTER_RTR) == 0U)) {
/* RTR bit does not match filter, drop frame */
err = can_mcan_write_reg(dev, fifo_ack_reg, get_idx);
if (err != 0) {
return;
}
goto ack;
} else if (fd_frame_filter != ((frame.flags & CAN_FRAME_FDF) != 0U)) {
/* FD bit does not match filter FD frame, drop frame */
}
if (((frame.flags & CAN_FRAME_FDF) != 0U && (flags & CAN_FILTER_FDF) == 0U) ||
((frame.flags & CAN_FRAME_FDF) == 0U && (flags & CAN_FILTER_FDF) != 0U)) {
/* FDF bit does not match filter, drop frame */
err = can_mcan_write_reg(dev, fifo_ack_reg, get_idx);
if (err != 0) {
return;
@ -670,17 +675,19 @@ static void can_mcan_get_message(const struct device *dev, uint16_t fifo_offset,
if ((frame.flags & CAN_FRAME_IDE) != 0) {
LOG_DBG("Frame on filter %d, ID: 0x%x",
filt_idx + NUM_STD_FILTER_DATA, frame.id);
cb = data->rx_cb_ext[filt_idx];
cb_arg = data->cb_arg_ext[filt_idx];
filt_idx + cbs->num_std, frame.id);
__ASSERT_NO_MSG(filt_idx <= cbs->num_ext);
cb = cbs->ext[filt_idx].function;
user_data = cbs->ext[filt_idx].user_data;
} else {
LOG_DBG("Frame on filter %d, ID: 0x%x", filt_idx, frame.id);
cb = data->rx_cb_std[filt_idx];
cb_arg = data->cb_arg_std[filt_idx];
__ASSERT_NO_MSG(filt_idx <= cbs->num_std);
cb = cbs->std[filt_idx].function;
user_data = cbs->std[filt_idx].user_data;
}
if (cb) {
cb(dev, &frame, cb_arg);
cb(dev, &frame, user_data);
} else {
LOG_DBG("cb missing");
}
@ -703,6 +710,7 @@ ack:
void can_mcan_line_1_isr(const struct device *dev)
{
const struct can_mcan_config *config = dev->config;
const uint32_t events =
CAN_MCAN_IR_RF0N | CAN_MCAN_IR_RF1N | CAN_MCAN_IR_RF0L | CAN_MCAN_IR_RF1L;
uint32_t ir;
@ -716,14 +724,14 @@ void can_mcan_line_1_isr(const struct device *dev)
while ((ir & events) != 0U) {
if ((ir & CAN_MCAN_IR_RF0N) != 0U) {
LOG_DBG("RX FIFO0 INT");
can_mcan_get_message(dev, CAN_MCAN_MRAM_OFFSET_RX_FIFO0, CAN_MCAN_RXF0S,
CAN_MCAN_RXF0A);
can_mcan_get_message(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_RX_FIFO0],
CAN_MCAN_RXF0S, CAN_MCAN_RXF0A);
}
if ((ir & CAN_MCAN_IR_RF1N) != 0U) {
LOG_DBG("RX FIFO1 INT");
can_mcan_get_message(dev, CAN_MCAN_MRAM_OFFSET_RX_FIFO1, CAN_MCAN_RXF1S,
CAN_MCAN_RXF1A);
can_mcan_get_message(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_RX_FIFO1],
CAN_MCAN_RXF1S, CAN_MCAN_RXF1A);
}
if ((ir & CAN_MCAN_IR_RF0L) != 0U) {
@ -801,6 +809,8 @@ int can_mcan_recover(const struct device *dev, k_timeout_t timeout)
int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_timeout_t timeout,
can_tx_callback_t callback, void *user_data)
{
const struct can_mcan_config *config = dev->config;
const struct can_mcan_callbacks *cbs = config->callbacks;
struct can_mcan_data *data = dev->data;
size_t data_length = can_dlc_to_bytes(frame->dlc);
struct can_mcan_tx_buffer_hdr tx_hdr = {
@ -901,7 +911,7 @@ int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_tim
tx_hdr.std_id = frame->id & CAN_STD_ID_MASK;
}
err = can_mcan_write_mram(dev, CAN_MCAN_MRAM_OFFSET_TX_BUFFER + put_idx *
err = can_mcan_write_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_TX_BUFFER] + put_idx *
sizeof(struct can_mcan_tx_buffer) +
offsetof(struct can_mcan_tx_buffer, hdr),
&tx_hdr, sizeof(struct can_mcan_tx_buffer_hdr));
@ -910,7 +920,7 @@ int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_tim
return err;
}
err = can_mcan_write_mram(dev, CAN_MCAN_MRAM_OFFSET_TX_BUFFER + put_idx *
err = can_mcan_write_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_TX_BUFFER] + put_idx *
sizeof(struct can_mcan_tx_buffer) +
offsetof(struct can_mcan_tx_buffer, data_32),
&frame->data_32, ROUND_UP(data_length, sizeof(uint32_t)));
@ -919,8 +929,9 @@ int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_tim
return err;
}
data->tx_fin_cb[put_idx] = callback;
data->tx_fin_cb_arg[put_idx] = user_data;
__ASSERT_NO_MSG(put_idx <= cbs->num_tx);
cbs->tx[put_idx].function = callback;
cbs->tx[put_idx].user_data = user_data;
err = can_mcan_write_reg(dev, CAN_MCAN_TXBAR, BIT(put_idx));
if (err != 0) {
@ -935,12 +946,14 @@ unlock:
static int can_mcan_get_free_std(const struct device *dev)
{
const struct can_mcan_config *config = dev->config;
const struct can_mcan_callbacks *cbs = config->callbacks;
struct can_mcan_std_filter filter;
int err;
int i;
for (i = 0; i < NUM_STD_FILTER_DATA; ++i) {
err = can_mcan_read_mram(dev, CAN_MCAN_MRAM_OFFSET_STD_FILTER +
for (i = 0; i < cbs->num_std; ++i) {
err = can_mcan_read_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_STD_FILTER] +
i * sizeof(struct can_mcan_std_filter), &filter,
sizeof(struct can_mcan_std_filter));
if (err != 0) {
@ -958,12 +971,13 @@ static int can_mcan_get_free_std(const struct device *dev)
int can_mcan_get_max_filters(const struct device *dev, bool ide)
{
ARG_UNUSED(dev);
const struct can_mcan_config *config = dev->config;
const struct can_mcan_callbacks *cbs = config->callbacks;
if (ide) {
return NUM_EXT_FILTER_DATA;
return cbs->num_ext;
} else {
return NUM_STD_FILTER_DATA;
return cbs->num_std;
}
}
@ -975,6 +989,8 @@ int can_mcan_get_max_filters(const struct device *dev, bool ide)
int can_mcan_add_rx_filter_std(const struct device *dev, can_rx_callback_t callback,
void *user_data, const struct can_filter *filter)
{
const struct can_mcan_config *config = dev->config;
const struct can_mcan_callbacks *cbs = config->callbacks;
struct can_mcan_data *data = dev->data;
struct can_mcan_std_filter filter_element = {
.id1 = filter->id,
@ -996,7 +1012,7 @@ int can_mcan_add_rx_filter_std(const struct device *dev, can_rx_callback_t callb
/* TODO proper fifo balancing */
filter_element.sfce = filter_id & 0x01 ? CAN_MCAN_FCE_FIFO1 : CAN_MCAN_FCE_FIFO0;
err = can_mcan_write_mram(dev, CAN_MCAN_MRAM_OFFSET_STD_FILTER +
err = can_mcan_write_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_STD_FILTER] +
filter_id * sizeof(struct can_mcan_std_filter),
&filter_element, sizeof(filter_element));
if (err != 0) {
@ -1008,39 +1024,24 @@ int can_mcan_add_rx_filter_std(const struct device *dev, can_rx_callback_t callb
LOG_DBG("Attached std filter at %d", filter_id);
if ((filter->flags & CAN_FILTER_RTR) != 0U) {
data->std_filt_rtr |= (1U << filter_id);
} else {
data->std_filt_rtr &= ~(1U << filter_id);
}
if ((filter->flags & (CAN_FILTER_DATA | CAN_FILTER_RTR)) !=
(CAN_FILTER_DATA | CAN_FILTER_RTR)) {
data->std_filt_rtr_mask |= (1U << filter_id);
} else {
data->std_filt_rtr_mask &= ~(1U << filter_id);
}
if ((filter->flags & CAN_FILTER_FDF) != 0U) {
data->std_filt_fd_frame |= (1U << filter_id);
} else {
data->std_filt_fd_frame &= ~(1U << filter_id);
}
data->rx_cb_std[filter_id] = callback;
data->cb_arg_std[filter_id] = user_data;
__ASSERT_NO_MSG(filter_id <= cbs->num_std);
cbs->std[filter_id].function = callback;
cbs->std[filter_id].user_data = user_data;
cbs->std[filter_id].flags = filter->flags;
return filter_id;
}
static int can_mcan_get_free_ext(const struct device *dev)
{
const struct can_mcan_config *config = dev->config;
const struct can_mcan_callbacks *cbs = config->callbacks;
struct can_mcan_ext_filter filter;
int err;
int i;
for (i = 0; i < NUM_EXT_FILTER_DATA; ++i) {
err = can_mcan_read_mram(dev, CAN_MCAN_MRAM_OFFSET_EXT_FILTER +
for (i = 0; i < cbs->num_ext; ++i) {
err = can_mcan_read_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_EXT_FILTER] +
i * sizeof(struct can_mcan_ext_filter), &filter,
sizeof(struct can_mcan_ext_filter));
if (err != 0) {
@ -1059,6 +1060,8 @@ static int can_mcan_get_free_ext(const struct device *dev)
static int can_mcan_add_rx_filter_ext(const struct device *dev, can_rx_callback_t callback,
void *user_data, const struct can_filter *filter)
{
const struct can_mcan_config *config = dev->config;
const struct can_mcan_callbacks *cbs = config->callbacks;
struct can_mcan_data *data = dev->data;
struct can_mcan_ext_filter filter_element = {
.id2 = filter->mask,
@ -1080,7 +1083,7 @@ static int can_mcan_add_rx_filter_ext(const struct device *dev, can_rx_callback_
/* TODO proper fifo balancing */
filter_element.efce = filter_id & 0x01 ? CAN_MCAN_FCE_FIFO1 : CAN_MCAN_FCE_FIFO0;
err = can_mcan_write_mram(dev, CAN_MCAN_MRAM_OFFSET_EXT_FILTER +
err = can_mcan_write_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_EXT_FILTER] +
filter_id * sizeof(struct can_mcan_ext_filter),
&filter_element, sizeof(filter_element));
if (err != 0) {
@ -1092,27 +1095,10 @@ static int can_mcan_add_rx_filter_ext(const struct device *dev, can_rx_callback_
LOG_DBG("Attached ext filter at %d", filter_id);
if ((filter->flags & CAN_FILTER_RTR) != 0U) {
data->ext_filt_rtr |= (1U << filter_id);
} else {
data->ext_filt_rtr &= ~(1U << filter_id);
}
if ((filter->flags & (CAN_FILTER_DATA | CAN_FILTER_RTR)) !=
(CAN_FILTER_DATA | CAN_FILTER_RTR)) {
data->ext_filt_rtr_mask |= (1U << filter_id);
} else {
data->ext_filt_rtr_mask &= ~(1U << filter_id);
}
if ((filter->flags & CAN_FILTER_FDF) != 0U) {
data->ext_filt_fd_frame |= (1U << filter_id);
} else {
data->ext_filt_fd_frame &= ~(1U << filter_id);
}
data->rx_cb_ext[filter_id] = callback;
data->cb_arg_ext[filter_id] = user_data;
__ASSERT_NO_MSG(filter_id <= cbs->num_ext);
cbs->ext[filter_id].function = callback;
cbs->ext[filter_id].user_data = user_data;
cbs->ext[filter_id].flags = filter->flags;
return filter_id;
}
@ -1120,6 +1106,8 @@ static int can_mcan_add_rx_filter_ext(const struct device *dev, can_rx_callback_
int can_mcan_add_rx_filter(const struct device *dev, can_rx_callback_t callback, void *user_data,
const struct can_filter *filter)
{
const struct can_mcan_config *config = dev->config;
const struct can_mcan_callbacks *cbs = config->callbacks;
int filter_id;
if (callback == NULL) {
@ -1139,7 +1127,7 @@ int can_mcan_add_rx_filter(const struct device *dev, can_rx_callback_t callback,
if ((filter->flags & CAN_FILTER_IDE) != 0U) {
filter_id = can_mcan_add_rx_filter_ext(dev, callback, user_data, filter);
if (filter_id >= 0) {
filter_id += NUM_STD_FILTER_DATA;
filter_id += cbs->num_std;
}
} else {
filter_id = can_mcan_add_rx_filter_std(dev, callback, user_data, filter);
@ -1150,27 +1138,29 @@ int can_mcan_add_rx_filter(const struct device *dev, can_rx_callback_t callback,
void can_mcan_remove_rx_filter(const struct device *dev, int filter_id)
{
const struct can_mcan_config *config = dev->config;
const struct can_mcan_callbacks *cbs = config->callbacks;
struct can_mcan_data *data = dev->data;
int err;
k_mutex_lock(&data->lock, K_FOREVER);
if (filter_id >= NUM_STD_FILTER_DATA) {
filter_id -= NUM_STD_FILTER_DATA;
if (filter_id >= NUM_EXT_FILTER_DATA) {
if (filter_id >= cbs->num_std) {
filter_id -= cbs->num_std;
if (filter_id >= cbs->num_ext) {
LOG_ERR("Wrong filter id");
k_mutex_unlock(&data->lock);
return;
}
err = can_mcan_clear_mram(dev, CAN_MCAN_MRAM_OFFSET_EXT_FILTER +
err = can_mcan_clear_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_EXT_FILTER] +
filter_id * sizeof(struct can_mcan_ext_filter),
sizeof(struct can_mcan_ext_filter));
if (err != 0) {
LOG_ERR("failed to clear ext filter element (err %d)", err);
}
} else {
err = can_mcan_clear_mram(dev, CAN_MCAN_MRAM_OFFSET_STD_FILTER +
err = can_mcan_clear_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_STD_FILTER] +
filter_id * sizeof(struct can_mcan_std_filter),
sizeof(struct can_mcan_std_filter));
if (err != 0) {
@ -1229,6 +1219,8 @@ unlock:
int can_mcan_configure_mram(const struct device *dev, uintptr_t mrba, uintptr_t mram)
{
const struct can_mcan_config *config = dev->config;
uint32_t addr;
uint32_t reg;
int err;
@ -1246,49 +1238,56 @@ int can_mcan_configure_mram(const struct device *dev, uintptr_t mrba, uintptr_t
can_mcan_enable_configuration_change(dev);
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_STD_FILTER) & CAN_MCAN_SIDFC_FLSSA) |
FIELD_PREP(CAN_MCAN_SIDFC_LSS, NUM_STD_FILTER_ELEMENTS);
addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_STD_FILTER];
reg = (addr & CAN_MCAN_SIDFC_FLSSA) | FIELD_PREP(CAN_MCAN_SIDFC_LSS,
config->mram_elements[CAN_MCAN_MRAM_CFG_STD_FILTER]);
err = can_mcan_write_reg(dev, CAN_MCAN_SIDFC, reg);
if (err != 0) {
return err;
}
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_EXT_FILTER) & CAN_MCAN_XIDFC_FLESA) |
FIELD_PREP(CAN_MCAN_XIDFC_LSS, NUM_EXT_FILTER_ELEMENTS);
addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_EXT_FILTER];
reg = (addr & CAN_MCAN_XIDFC_FLESA) | FIELD_PREP(CAN_MCAN_XIDFC_LSS,
config->mram_elements[CAN_MCAN_MRAM_CFG_EXT_FILTER]);
err = can_mcan_write_reg(dev, CAN_MCAN_XIDFC, reg);
if (err != 0) {
return err;
}
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_RX_FIFO0) & CAN_MCAN_RXF0C_F0SA) |
FIELD_PREP(CAN_MCAN_RXF0C_F0S, NUM_RX_FIFO0_ELEMENTS);
addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_RX_FIFO0];
reg = (addr & CAN_MCAN_RXF0C_F0SA) | FIELD_PREP(CAN_MCAN_RXF0C_F0S,
config->mram_elements[CAN_MCAN_MRAM_CFG_RX_FIFO0]);
err = can_mcan_write_reg(dev, CAN_MCAN_RXF0C, reg);
if (err != 0) {
return err;
}
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_RX_FIFO1) & CAN_MCAN_RXF1C_F1SA) |
FIELD_PREP(CAN_MCAN_RXF1C_F1S, NUM_RX_FIFO1_ELEMENTS);
addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_RX_FIFO1];
reg = (addr & CAN_MCAN_RXF1C_F1SA) | FIELD_PREP(CAN_MCAN_RXF1C_F1S,
config->mram_elements[CAN_MCAN_MRAM_CFG_RX_FIFO1]);
err = can_mcan_write_reg(dev, CAN_MCAN_RXF1C, reg);
if (err != 0) {
return err;
}
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_RX_BUFFER) & CAN_MCAN_RXBC_RBSA);
addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_RX_BUFFER];
reg = (addr & CAN_MCAN_RXBC_RBSA);
err = can_mcan_write_reg(dev, CAN_MCAN_RXBC, reg);
if (err != 0) {
return err;
}
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_TX_EVENT_FIFO) & CAN_MCAN_TXEFC_EFSA) |
FIELD_PREP(CAN_MCAN_TXEFC_EFS, NUM_TX_EVENT_FIFO_ELEMENTS);
addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_TX_EVENT_FIFO];
reg = (addr & CAN_MCAN_TXEFC_EFSA) | FIELD_PREP(CAN_MCAN_TXEFC_EFS,
config->mram_elements[CAN_MCAN_MRAM_CFG_TX_EVENT_FIFO]);
err = can_mcan_write_reg(dev, CAN_MCAN_TXEFC, reg);
if (err != 0) {
return err;
}
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_TX_BUFFER) & CAN_MCAN_TXBC_TBSA) |
FIELD_PREP(CAN_MCAN_TXBC_TFQS, NUM_TX_BUF_ELEMENTS) | CAN_MCAN_TXBC_TFQM;
addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_TX_BUFFER];
reg = (addr & CAN_MCAN_TXBC_TBSA) | FIELD_PREP(CAN_MCAN_TXBC_TFQS,
config->mram_elements[CAN_MCAN_MRAM_CFG_TX_BUFFER]) | CAN_MCAN_TXBC_TFQM;
err = can_mcan_write_reg(dev, CAN_MCAN_TXBC, reg);
if (err != 0) {
return err;
@ -1314,6 +1313,7 @@ int can_mcan_configure_mram(const struct device *dev, uintptr_t mrba, uintptr_t
int can_mcan_init(const struct device *dev)
{
const struct can_mcan_config *config = dev->config;
const struct can_mcan_callbacks *cbs = config->callbacks;
struct can_mcan_data *data = dev->data;
struct can_timing timing;
#ifdef CONFIG_CAN_FD_MODE
@ -1327,10 +1327,15 @@ int can_mcan_init(const struct device *dev)
__ASSERT_NO_MSG(config->ops->read_mram != NULL);
__ASSERT_NO_MSG(config->ops->write_mram != NULL);
__ASSERT_NO_MSG(config->ops->clear_mram != NULL);
__ASSERT_NO_MSG(config->callbacks != NULL);
__ASSERT_NO_MSG(cbs->num_tx <= config->mram_elements[CAN_MCAN_MRAM_CFG_TX_BUFFER]);
__ASSERT_NO_MSG(cbs->num_std <= config->mram_elements[CAN_MCAN_MRAM_CFG_STD_FILTER]);
__ASSERT_NO_MSG(cbs->num_ext <= config->mram_elements[CAN_MCAN_MRAM_CFG_EXT_FILTER]);
k_mutex_init(&data->lock);
k_mutex_init(&data->tx_mtx);
k_sem_init(&data->tx_sem, NUM_TX_BUF_ELEMENTS, NUM_TX_BUF_ELEMENTS);
k_sem_init(&data->tx_sem, cbs->num_tx, cbs->num_tx);
if (config->phy != NULL) {
if (!device_is_ready(config->phy)) {
@ -1503,5 +1508,5 @@ int can_mcan_init(const struct device *dev)
return err;
}
return can_mcan_clear_mram(dev, 0, sizeof(struct can_mcan_msg_sram));
return can_mcan_clear_mram(dev, 0, config->mram_size);
}

View file

@ -384,27 +384,34 @@
#define CAN_MCAN_TXEFA 0x0F8
#define CAN_MCAN_TXEFA_EFAI GENMASK(4, 0)
#ifdef CONFIG_CAN_MCUX_MCAN
#define MCAN_DT_PATH DT_NODELABEL(can0)
#else
#define MCAN_DT_PATH DT_PATH(soc, can)
#endif
/**
* @brief Indexes for the cells in the devicetree bosch,mram-cfg property. These match the
* description of the cells in the bosch,m_can-base devicetree binding.
* @name Indexes for the cells in the devicetree bosch,mram-cfg property
* @anchor CAN_MCAN_MRAM_CFG
* These match the description of the cells in the bosch,m_can-base devicetree binding.
*
* @{
*/
enum can_mcan_mram_cfg {
CAN_MCAN_MRAM_CFG_OFFSET = 0,
CAN_MCAN_MRAM_CFG_STD_FILTER,
CAN_MCAN_MRAM_CFG_EXT_FILTER,
CAN_MCAN_MRAM_CFG_RX_FIFO0,
CAN_MCAN_MRAM_CFG_RX_FIFO1,
CAN_MCAN_MRAM_CFG_RX_BUFFER,
CAN_MCAN_MRAM_CFG_TX_EVENT,
CAN_MCAN_MRAM_CFG_TX_BUFFER,
CAN_MCAN_MRAM_CFG_NUM_CELLS
};
/** offset cell index */
#define CAN_MCAN_MRAM_CFG_OFFSET 0
/** std-filter-elements cell index */
#define CAN_MCAN_MRAM_CFG_STD_FILTER 1
/** ext-filter-elements cell index */
#define CAN_MCAN_MRAM_CFG_EXT_FILTER 2
/** rx-fifo0-elements cell index */
#define CAN_MCAN_MRAM_CFG_RX_FIFO0 3
/** rx-fifo1-elements cell index */
#define CAN_MCAN_MRAM_CFG_RX_FIFO1 4
/** rx-buffer-elements cell index */
#define CAN_MCAN_MRAM_CFG_RX_BUFFER 5
/** tx-event-fifo-elements cell index */
#define CAN_MCAN_MRAM_CFG_TX_EVENT_FIFO 6
/** tx-buffer-elements cell index */
#define CAN_MCAN_MRAM_CFG_TX_BUFFER 7
/** Total number of cells in bosch,mram-cfg property */
#define CAN_MCAN_MRAM_CFG_NUM_CELLS 8
/** @} */
/**
* @brief Get the Bosch M_CAN Message RAM offset
@ -412,8 +419,8 @@ enum can_mcan_mram_cfg {
* @param node_id node identifier
* @return the Message RAM offset in bytes
*/
#define CAN_MCAN_DT_MRAM_OFFSET(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 0)
#define CAN_MCAN_DT_MRAM_OFFSET(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, CAN_MCAN_MRAM_CFG_OFFSET)
/**
* @brief Get the number of standard (11-bit) filter elements in Bosch M_CAN Message RAM
@ -421,8 +428,8 @@ enum can_mcan_mram_cfg {
* @param node_id node identifier
* @return the number of standard (11-bit) filter elements
*/
#define CAN_MCAN_DT_MRAM_STD_FILTER_ELEM(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 1)
#define CAN_MCAN_DT_MRAM_STD_FILTER_ELEMENTS(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, CAN_MCAN_MRAM_CFG_STD_FILTER)
/**
* @brief Get the number of extended (29-bit) filter elements in Bosch M_CAN Message RAM
@ -430,8 +437,8 @@ enum can_mcan_mram_cfg {
* @param node_id node identifier
* @return the number of extended (29-bit) filter elements
*/
#define CAN_MCAN_DT_MRAM_EXT_FILTER_ELEM(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 2)
#define CAN_MCAN_DT_MRAM_EXT_FILTER_ELEMENTS(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, CAN_MCAN_MRAM_CFG_EXT_FILTER)
/**
* @brief Get the number of Rx FIFO 0 elements in Bosch M_CAN Message RAM
@ -439,8 +446,8 @@ enum can_mcan_mram_cfg {
* @param node_id node identifier
* @return the number of Rx FIFO 0 elements
*/
#define CAN_MCAN_DT_MRAM_RX_FIFO0_ELEM(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 3)
#define CAN_MCAN_DT_MRAM_RX_FIFO0_ELEMENTS(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, CAN_MCAN_MRAM_CFG_RX_FIFO0)
/**
* @brief Get the number of Rx FIFO 1 elements in Bosch M_CAN Message RAM
@ -448,8 +455,8 @@ enum can_mcan_mram_cfg {
* @param node_id node identifier
* @return the number of Rx FIFO 1 elements
*/
#define CAN_MCAN_DT_MRAM_RX_FIFO1_ELEM(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 4)
#define CAN_MCAN_DT_MRAM_RX_FIFO1_ELEMENTS(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, CAN_MCAN_MRAM_CFG_RX_FIFO1)
/**
* @brief Get the number of Rx Buffer elements in Bosch M_CAN Message RAM
@ -457,8 +464,8 @@ enum can_mcan_mram_cfg {
* @param node_id node identifier
* @return the number of Rx Buffer elements
*/
#define CAN_MCAN_DT_MRAM_RX_BUFFER_ELEM(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 5)
#define CAN_MCAN_DT_MRAM_RX_BUFFER_ELEMENTS(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, CAN_MCAN_MRAM_CFG_RX_BUFFER)
/**
* @brief Get the number of Tx Event FIFO elements in Bosch M_CAN Message RAM
@ -466,8 +473,8 @@ enum can_mcan_mram_cfg {
* @param node_id node identifier
* @return the number of Tx Event FIFO elements
*/
#define CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEM(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 6)
#define CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEMENTS(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, CAN_MCAN_MRAM_CFG_TX_EVENT_FIFO)
/**
* @brief Get the number of Tx Buffer elements in Bosch M_CAN Message RAM
@ -475,8 +482,163 @@ enum can_mcan_mram_cfg {
* @param node_id node identifier
* @return the number of Tx Buffer elements
*/
#define CAN_MCAN_DT_MRAM_TX_BUFFER_ELEM(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 7)
#define CAN_MCAN_DT_MRAM_TX_BUFFER_ELEMENTS(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, CAN_MCAN_MRAM_CFG_TX_BUFFER)
/**
* @brief Get the base offset of standard (11-bit) filter elements in Bosch M_CAN Message RAM
*
* @param node_id node identifier
* @return the base offset of standard (11-bit) filter elements in bytes
*/
#define CAN_MCAN_DT_MRAM_STD_FILTER_OFFSET(node_id) (0U)
/**
* @brief Get the base offset of extended (29-bit) filter elements in Bosch M_CAN Message RAM
*
* @param node_id node identifier
* @return the base offset of extended (29-bit) filter elements in bytes
*/
#define CAN_MCAN_DT_MRAM_EXT_FILTER_OFFSET(node_id) \
(CAN_MCAN_DT_MRAM_STD_FILTER_OFFSET(node_id) + \
CAN_MCAN_DT_MRAM_STD_FILTER_ELEMENTS(node_id) * sizeof(struct can_mcan_std_filter))
/**
* @brief Get the base offset of Rx FIFO 0 elements in Bosch M_CAN Message RAM
*
* @param node_id node identifier
* @return the base offset of Rx FIFO 0 elements in bytes
*/
#define CAN_MCAN_DT_MRAM_RX_FIFO0_OFFSET(node_id) \
(CAN_MCAN_DT_MRAM_EXT_FILTER_OFFSET(node_id) + \
CAN_MCAN_DT_MRAM_EXT_FILTER_ELEMENTS(node_id) * sizeof(struct can_mcan_ext_filter))
/**
* @brief Get the base offset of Rx FIFO 1 elements in Bosch M_CAN Message RAM
*
* @param node_id node identifier
* @return the base offset of Rx FIFO 1 elements in bytes
*/
#define CAN_MCAN_DT_MRAM_RX_FIFO1_OFFSET(node_id) \
(CAN_MCAN_DT_MRAM_RX_FIFO0_OFFSET(node_id) + \
CAN_MCAN_DT_MRAM_RX_FIFO0_ELEMENTS(node_id) * sizeof(struct can_mcan_rx_fifo))
/**
* @brief Get the base offset of Rx Buffer elements in Bosch M_CAN Message RAM
*
* @param node_id node identifier
* @return the base offset of Rx Buffer elements in bytes
*/
#define CAN_MCAN_DT_MRAM_RX_BUFFER_OFFSET(node_id) \
(CAN_MCAN_DT_MRAM_RX_FIFO1_OFFSET(node_id) + \
CAN_MCAN_DT_MRAM_RX_FIFO1_ELEMENTS(node_id) * sizeof(struct can_mcan_rx_fifo))
/**
* @brief Get the base offset of Tx Event FIFO elements in Bosch M_CAN Message RAM
*
* @param node_id node identifier
* @return the base offset of Tx Event FIFO elements in bytes
*/
#define CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_OFFSET(node_id) \
(CAN_MCAN_DT_MRAM_RX_BUFFER_OFFSET(node_id) + \
CAN_MCAN_DT_MRAM_RX_BUFFER_ELEMENTS(node_id) * sizeof(struct can_mcan_rx_fifo))
/**
* @brief Get the base offset of Tx Buffer elements in Bosch M_CAN Message RAM
*
* @param node_id node identifier
* @return the base offset of Tx Buffer elements in bytes
*/
#define CAN_MCAN_DT_MRAM_TX_BUFFER_OFFSET(node_id) \
(CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_OFFSET(node_id) + \
CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEMENTS(node_id) * sizeof(struct can_mcan_tx_event_fifo))
/**
* @brief Get the Bosch M_CAN register base address
*
* For devicetree nodes with just one register block, this macro returns the base address of that
* register block.
*
* If a devicetree node has more than one register block, this macros returns the base address of
* the register block named "m_can".
*
* @param node_id node identifier
* @return the Bosch M_CAN register base address
*/
#define CAN_MCAN_DT_MCAN_ADDR(node_id) \
COND_CODE_1(DT_NUM_REGS(node_id), ((mm_reg_t)DT_REG_ADDR(node_id)), \
((mm_reg_t)DT_REG_ADDR_BY_NAME(node_id, m_can)))
/**
* @brief Get the Bosch M_CAN Message RAM base address
*
* For devicetree nodes with dedicated Message RAM area defined via devicetree, this macro returns
* the base address of the Message RAM, taking in the Message RAM offset into account.
*
* @param node_id node identifier
* @return the Bosch M_CAN Message RAM base address
*/
#define CAN_MCAN_DT_MRAM_ADDR(node_id) \
(mem_addr_t)(DT_REG_ADDR_BY_NAME(node_id, message_ram) + CAN_MCAN_DT_MRAM_OFFSET(node_id))
/**
* @brief Get the Bosch M_CAN Message RAM size
*
* For devicetree nodes with dedicated Message RAM area defined via devicetree, this macro returns
* the size of the Message RAM, taking in the Message RAM offset into account.
*
* @param node_id node identifier
* @return the Bosch M_CAN Message RAM base address
* @see CAN_MCAN_DT_MRAM_ELEMENTS_SIZE()
*/
#define CAN_MCAN_DT_MRAM_SIZE(node_id) \
(mem_addr_t)(DT_REG_SIZE_BY_NAME(node_id, message_ram) - CAN_MCAN_DT_MRAM_OFFSET(node_id))
/**
* @brief Get the total size of all Bosch M_CAN Message RAM elements
*
* @param node_id node identifier
* @return the total size of all Message RAM elements in bytes
* @see CAN_MCAN_DT_MRAM_SIZE()
*/
#define CAN_MCAN_DT_MRAM_ELEMENTS_SIZE(node_id) \
(CAN_MCAN_DT_MRAM_TX_BUFFER_OFFSET(node_id) + \
CAN_MCAN_DT_MRAM_TX_BUFFER_ELEMENTS(node_id) * sizeof(struct can_mcan_tx_buffer))
/**
* @brief Define a RAM buffer for Bosch M_CAN Message RAM
*
* For devicetree nodes without dedicated Message RAM area, this macro defines a suitable RAM buffer
* to hold the Message RAM elements. Since this buffer cannot be shared between multiple Bosch M_CAN
* instances, the Message RAM offset must be set to 0x0.
*
* @param node_id node identifier
* @param _name buffer variable name
*/
#define CAN_MCAN_DT_MRAM_DEFINE(node_id, _name) \
BUILD_ASSERT(CAN_MCAN_DT_MRAM_OFFSET(node_id) == 0, "offset must be 0"); \
static char __noinit __nocache __aligned(4) _name[CAN_MCAN_DT_MRAM_ELEMENTS_SIZE(node_id)];
/**
* @brief Assert that the Message RAM configuration meets the Bosch M_CAN IP core restrictions
*
* @param node_id node identifier
*/
#define CAN_MCAN_DT_BUILD_ASSERT_MRAM_CFG(node_id) \
BUILD_ASSERT(CAN_MCAN_DT_MRAM_STD_FILTER_ELEMENTS(node_id) <= 128, \
"Maximum Standard filter elements exceeded"); \
BUILD_ASSERT(CAN_MCAN_DT_MRAM_EXT_FILTER_ELEMENTS(node_id) <= 64, \
"Maximum Extended filter elements exceeded"); \
BUILD_ASSERT(CAN_MCAN_DT_MRAM_RX_FIFO0_ELEMENTS(node_id) <= 64, \
"Maximum Rx FIFO 0 elements exceeded"); \
BUILD_ASSERT(CAN_MCAN_DT_MRAM_RX_FIFO1_ELEMENTS(node_id) <= 64, \
"Maximum Rx FIFO 1 elements exceeded"); \
BUILD_ASSERT(CAN_MCAN_DT_MRAM_RX_BUFFER_ELEMENTS(node_id) <= 64, \
"Maximum Rx Buffer elements exceeded"); \
BUILD_ASSERT(CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEMENTS(node_id) <= 32, \
"Maximum Tx Buffer elements exceeded"); \
BUILD_ASSERT(CAN_MCAN_DT_MRAM_TX_BUFFER_ELEMENTS(node_id) <= 32, \
"Maximum Tx Buffer elements exceeded");
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_OFFSET(DT_DRV_INST(inst))
@ -484,96 +646,181 @@ enum can_mcan_mram_cfg {
* @return the Message RAM offset in bytes
* @see CAN_MCAN_DT_MRAM_OFFSET()
*/
#define CAN_MCAN_DT_INST_MRAM_OFFSET(inst) \
CAN_MCAN_DT_MRAM_OFFSET(DT_DRV_INST(inst))
#define CAN_MCAN_DT_INST_MRAM_OFFSET(inst) CAN_MCAN_DT_MRAM_OFFSET(DT_DRV_INST(inst))
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_STD_FILTER_ELEM(DT_DRV_INST(inst))
* @brief Equivalent to CAN_MCAN_DT_MRAM_STD_FILTER_ELEMENTS(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the number of standard (11-bit) elements
* @see CAN_MCAN_DT_MRAM_STD_FILTER_ELEM()
* @see CAN_MCAN_DT_MRAM_STD_FILTER_ELEMENTS()
*/
#define CAN_MCAN_DT_INST_MRAM_STD_FILTER_ELEM(inst) \
CAN_MCAN_DT_MRAM_STD_FILTER_ELEMDT_DRV_INST(inst))
#define CAN_MCAN_DT_INST_MRAM_STD_FILTER_ELEMENTS(inst) \
CAN_MCAN_DT_MRAM_STD_FILTER_ELEMENTS(DT_DRV_INST(inst))
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_EXT_FILTER_ELEM(DT_DRV_INST(inst))
* @brief Equivalent to CAN_MCAN_DT_MRAM_EXT_FILTER_ELEMENTS(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the number of extended (29-bit) elements
* @see CAN_MCAN_DT_MRAM_EXT_FILTER_ELEM()
* @see CAN_MCAN_DT_MRAM_EXT_FILTER_ELEMENTS()
*/
#define CAN_MCAN_DT_INST_MRAM_EXT_FILTER_ELEM(inst) \
CAN_MCAN_DT_MRAM_EXT_FILTER_ELEM(DT_DRV_INST(inst))
#define CAN_MCAN_DT_INST_MRAM_EXT_FILTER_ELEMENTS(inst) \
CAN_MCAN_DT_MRAM_EXT_FILTER_ELEMENTS(DT_DRV_INST(inst))
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_FIFO0_ELEM(DT_DRV_INST(inst))
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_FIFO0_ELEMENTS(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the number of Rx FIFO 0 elements
* @see CAN_MCAN_DT_MRAM_RX_FIFO0_ELEM()
* @see CAN_MCAN_DT_MRAM_RX_FIFO0_ELEMENTS()
*/
#define CAN_MCAN_DT_INST_MRAM_RX_FIFO0_ELEM(inst) \
CAN_MCAN_DT_MRAM_RX_FIFO0_ELEM(DT_DRV_INST(inst))
#define CAN_MCAN_DT_INST_MRAM_RX_FIFO0_ELEMENTS(inst) \
CAN_MCAN_DT_MRAM_RX_FIFO0_ELEMENTS(DT_DRV_INST(inst))
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_FIFO1_ELEM(DT_DRV_INST(inst))
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_FIFO1_ELEMENTS(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the number of Rx FIFO 1 elements
* @see CAN_MCAN_DT_MRAM_RX_FIFO1_ELEM()
* @see CAN_MCAN_DT_MRAM_RX_FIFO1_ELEMENTS()
*/
#define CAN_MCAN_DT_INST_MRAM_RX_FIFO1_ELEM(inst) \
CAN_MCAN_DT_MRAM_RX_FIFO1_ELEM(DT_DRV_INST(inst))
#define CAN_MCAN_DT_INST_MRAM_RX_FIFO1_ELEMENTS(inst) \
CAN_MCAN_DT_MRAM_RX_FIFO1_ELEMENTS(DT_DRV_INST(inst))
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_BUFFER_ELEM(DT_DRV_INST(inst))
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_BUFFER_ELEMENTS(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the number of Rx Buffer elements
* @see CAN_MCAN_DT_MRAM_RX_BUFFER_ELEM()
* @see CAN_MCAN_DT_MRAM_RX_BUFFER_ELEMENTS()
*/
#define CAN_MCAN_DT_INST_MRAM_RX_BUFFER_ELEM(inst) \
CAN_MCAN_DT_MRAM_RX_BUFFER_ELEM(DT_DRV_INST(inst))
#define CAN_MCAN_DT_INST_MRAM_RX_BUFFER_ELEMENTS(inst) \
CAN_MCAN_DT_MRAM_RX_BUFFER_ELEMENTS(DT_DRV_INST(inst))
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_TX_EVENT_ELEM(DT_DRV_INST(inst))
* @brief Equivalent to CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEMENTS(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the number of Tx Event FIFO elements
* @see CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEM()
* @see CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEMENTS()
*/
#define CAN_MCAN_DT_INST_MRAM_TX_EVENT_FIFO_ELEM(inst) \
CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEM(DT_DRV_INST(inst))
#define CAN_MCAN_DT_INST_MRAM_TX_EVENT_FIFO_ELEMENTS(inst) \
CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEMENTS(DT_DRV_INST(inst))
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_TX_BUFFER_ELEM(DT_DRV_INST(inst))
* @brief Equivalent to CAN_MCAN_DT_MRAM_TX_BUFFER_ELEMENTS(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the number of Tx Buffer elements
* @see CAN_MCAN_DT_MRAM_TX_BUFFER_ELEM()
* @see CAN_MCAN_DT_MRAM_TX_BUFFER_ELEMENTS()
*/
#define CAN_MCAN_DT_INST_MRAM_TX_BUFFER_ELEM(inst) \
CAN_MCAN_DT_MRAM_TX_BUFFER_ELEM(DT_DRV_INST(inst))
#define CAN_MCAN_DT_INST_MRAM_TX_BUFFER_ELEMENTS(inst) \
CAN_MCAN_DT_MRAM_TX_BUFFER_ELEMENTS(DT_DRV_INST(inst))
#define NUM_STD_FILTER_ELEMENTS CAN_MCAN_DT_MRAM_STD_FILTER_ELEM(MCAN_DT_PATH)
#define NUM_EXT_FILTER_ELEMENTS CAN_MCAN_DT_MRAM_EXT_FILTER_ELEM(MCAN_DT_PATH)
#define NUM_RX_FIFO0_ELEMENTS CAN_MCAN_DT_MRAM_RX_FIFO0_ELEM(MCAN_DT_PATH)
#define NUM_RX_FIFO1_ELEMENTS CAN_MCAN_DT_MRAM_RX_FIFO1_ELEM(MCAN_DT_PATH)
#define NUM_RX_BUF_ELEMENTS CAN_MCAN_DT_MRAM_RX_BUFFER_ELEM(MCAN_DT_PATH)
#define NUM_TX_EVENT_FIFO_ELEMENTS CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEM(MCAN_DT_PATH)
#define NUM_TX_BUF_ELEMENTS CAN_MCAN_DT_MRAM_TX_BUFFER_ELEM(MCAN_DT_PATH)
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_STD_FILTER_OFFSET(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the base offset of standard (11-bit) filter elements in bytes
* @see CAN_MCAN_DT_MRAM_STD_FILTER_OFFSET()
*/
#define CAN_MCAN_DT_INST_MRAM_STD_FILTER_OFFSET(inst) \
CAN_MCAN_DT_MRAM_STD_FILTER_OFFSET(DT_DRV_INST(inst))
/* Assert that the Message RAM configuration meets the M_CAN IP core restrictions */
BUILD_ASSERT(NUM_STD_FILTER_ELEMENTS <= 128, "Maximum Standard filter elements exceeded");
BUILD_ASSERT(NUM_EXT_FILTER_ELEMENTS <= 64, "Maximum Extended filter elements exceeded");
BUILD_ASSERT(NUM_RX_FIFO0_ELEMENTS <= 64, "Maximum Rx FIFO 0 elements exceeded");
BUILD_ASSERT(NUM_RX_FIFO1_ELEMENTS <= 64, "Maximum Rx FIFO 1 elements exceeded");
BUILD_ASSERT(NUM_RX_BUF_ELEMENTS <= 64, "Maximum Rx Buffer elements exceeded");
BUILD_ASSERT(NUM_TX_EVENT_FIFO_ELEMENTS <= 32, "Maximum Tx Buffer elements exceeded");
BUILD_ASSERT(NUM_TX_BUF_ELEMENTS <= 32, "Maximum Tx Buffer elements exceeded");
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_EXT_FILTER_OFFSET(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the base offset of extended (29-bit) filter elements in bytes
* @see CAN_MCAN_DT_MRAM_EXT_FILTER_OFFSET()
*/
#define CAN_MCAN_DT_INST_MRAM_EXT_FILTER_OFFSET(inst) \
CAN_MCAN_DT_MRAM_EXT_FILTER_OFFSET(DT_DRV_INST(inst))
#ifdef CONFIG_CAN_STM32FD
#define NUM_STD_FILTER_DATA CONFIG_CAN_MAX_STD_ID_FILTER
#define NUM_EXT_FILTER_DATA CONFIG_CAN_MAX_EXT_ID_FILTER
#else
#define NUM_STD_FILTER_DATA NUM_STD_FILTER_ELEMENTS
#define NUM_EXT_FILTER_DATA NUM_EXT_FILTER_ELEMENTS
#endif
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_FIFO0_OFFSET(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the base offset of Rx FIFO 0 elements in bytes
* @see CAN_MCAN_DT_MRAM_RX_FIFO0_OFFSET()
*/
#define CAN_MCAN_DT_INST_MRAM_RX_FIFO0_OFFSET(inst) \
CAN_MCAN_DT_MRAM_RX_FIFO0_OFFSET(DT_DRV_INST(inst))
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_FIFO1_OFFSET(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the base offset of Rx FIFO 1 elements in bytes
* @see CAN_MCAN_DT_MRAM_RX_FIFO1_OFFSET()
*/
#define CAN_MCAN_DT_INST_MRAM_RX_FIFO1_OFFSET(inst) \
CAN_MCAN_DT_MRAM_RX_FIFO1_OFFSET(DT_DRV_INST(inst))
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_BUFFER_OFFSET(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the base offset of Rx Buffer elements in bytes
* @see CAN_MCAN_DT_MRAM_RX_BUFFER_OFFSET()
*/
#define CAN_MCAN_DT_INST_MRAM_RX_BUFFER_OFFSET(inst) \
CAN_MCAN_DT_MRAM_RX_BUFFER_OFFSET(DT_DRV_INST(inst))
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_OFFSET(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the base offset of Tx Event FIFO elements in bytes
* @see CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_OFFSET()
*/
#define CAN_MCAN_DT_INST_MRAM_TX_EVENT_FIFO_OFFSET(inst) \
CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_OFFSET(DT_DRV_INST(inst))
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_TX_BUFFER_OFFSET(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the base offset of Tx Buffer elements in bytes
* @see CAN_MCAN_DT_MRAM_TX_BUFFER_OFFSET()
*/
#define CAN_MCAN_DT_INST_MRAM_TX_BUFFER_OFFSET(inst) \
CAN_MCAN_DT_MRAM_TX_BUFFER_OFFSET(DT_DRV_INST(inst))
/**
* @brief Equivalent to CAN_MCAN_DT_MCAN_ADDR(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the Bosch M_CAN register base address
* @see CAN_MCAN_DT_MRAM_ADDR()
*/
#define CAN_MCAN_DT_INST_MCAN_ADDR(inst) CAN_MCAN_DT_MCAN_ADDR(DT_DRV_INST(inst))
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_ADDR(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the Bosch M_CAN Message RAM base address
* @see CAN_MCAN_DT_MRAM_ADDR()
*/
#define CAN_MCAN_DT_INST_MRAM_ADDR(inst) CAN_MCAN_DT_MRAM_ADDR(DT_DRV_INST(inst))
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_SIZE(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the Bosch M_CAN Message RAM size in bytes
* @see CAN_MCAN_DT_MRAM_SIZE()
*/
#define CAN_MCAN_DT_INST_MRAM_SIZE(inst) CAN_MCAN_DT_MRAM_SIZE(DT_DRV_INST(inst))
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_ELEMENTS_SIZE(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @return the total size of all Message RAM elements in bytes
* @see CAN_MCAN_DT_MRAM_ELEMENTS_SIZE()
*/
#define CAN_MCAN_DT_INST_MRAM_ELEMENTS_SIZE(inst) CAN_MCAN_DT_MRAM_ELEMENTS_SIZE(DT_DRV_INST(inst))
/**
* @brief Equivalent to CAN_MCAN_DT_MRAM_DEFINE(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @param _name buffer variable name
* @see CAN_MCAN_DT_MRAM_DEFINE()
*/
#define CAN_MCAN_DT_INST_MRAM_DEFINE(inst, _name) CAN_MCAN_DT_MRAM_DEFINE(DT_DRV_INST(inst), _name)
/**
* @brief Equivalent to CAN_MCAN_DT_BUILD_ASSERT_MRAM_CFG(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @see CAN_MCAN_DT_BUILD_ASSERT_MRAM_CFG()
*/
#define CAN_MCAN_DT_INST_BUILD_ASSERT_MRAM_CFG(inst) \
CAN_MCAN_DT_BUILD_ASSERT_MRAM_CFG(DT_DRV_INST(inst))
struct can_mcan_rx_fifo_hdr {
union {
@ -689,42 +936,12 @@ struct can_mcan_ext_filter {
uint32_t eft: 2; /* Filter type */
} __packed __aligned(4);
struct can_mcan_msg_sram {
struct can_mcan_std_filter std_filt[NUM_STD_FILTER_ELEMENTS];
struct can_mcan_ext_filter ext_filt[NUM_EXT_FILTER_ELEMENTS];
struct can_mcan_rx_fifo rx_fifo0[NUM_RX_FIFO0_ELEMENTS];
struct can_mcan_rx_fifo rx_fifo1[NUM_RX_FIFO1_ELEMENTS];
struct can_mcan_rx_fifo rx_buffer[NUM_RX_BUF_ELEMENTS];
struct can_mcan_tx_event_fifo tx_event_fifo[NUM_TX_EVENT_FIFO_ELEMENTS];
struct can_mcan_tx_buffer tx_buffer[NUM_TX_BUF_ELEMENTS];
} __packed __aligned(4);
#define CAN_MCAN_MRAM_OFFSET_STD_FILTER offsetof(struct can_mcan_msg_sram, std_filt)
#define CAN_MCAN_MRAM_OFFSET_EXT_FILTER offsetof(struct can_mcan_msg_sram, ext_filt)
#define CAN_MCAN_MRAM_OFFSET_RX_FIFO0 offsetof(struct can_mcan_msg_sram, rx_fifo0)
#define CAN_MCAN_MRAM_OFFSET_RX_FIFO1 offsetof(struct can_mcan_msg_sram, rx_fifo1)
#define CAN_MCAN_MRAM_OFFSET_RX_BUFFER offsetof(struct can_mcan_msg_sram, rx_buffer)
#define CAN_MCAN_MRAM_OFFSET_TX_EVENT_FIFO offsetof(struct can_mcan_msg_sram, tx_event_fifo)
#define CAN_MCAN_MRAM_OFFSET_TX_BUFFER offsetof(struct can_mcan_msg_sram, tx_buffer)
struct can_mcan_data {
struct k_mutex lock;
struct k_sem tx_sem;
struct k_mutex tx_mtx;
can_tx_callback_t tx_fin_cb[NUM_TX_BUF_ELEMENTS];
void *tx_fin_cb_arg[NUM_TX_BUF_ELEMENTS];
can_rx_callback_t rx_cb_std[NUM_STD_FILTER_DATA];
can_rx_callback_t rx_cb_ext[NUM_EXT_FILTER_DATA];
void *cb_arg_std[NUM_STD_FILTER_DATA];
void *cb_arg_ext[NUM_EXT_FILTER_DATA];
can_state_change_callback_t state_change_cb;
void *state_change_cb_data;
uint32_t std_filt_fd_frame;
uint32_t std_filt_rtr;
uint32_t std_filt_rtr_mask;
uint16_t ext_filt_fd_frame;
uint16_t ext_filt_rtr;
uint16_t ext_filt_rtr_mask;
bool started;
#ifdef CONFIG_CAN_FD_MODE
bool fd;
@ -814,8 +1031,90 @@ struct can_mcan_ops {
can_mcan_clear_mram_t clear_mram;
};
/**
* @brief Bosch M_CAN driver internal Tx callback structure.
*/
struct can_mcan_tx_callback {
can_tx_callback_t function;
void *user_data;
};
/**
* @brief Bosch M_CAN driver internal Rx callback structure.
*/
struct can_mcan_rx_callback {
can_rx_callback_t function;
void *user_data;
uint8_t flags;
};
/**
* @brief Bosch M_CAN driver internal Tx + Rx callbacks structure.
*/
struct can_mcan_callbacks {
struct can_mcan_tx_callback *tx;
struct can_mcan_rx_callback *std;
struct can_mcan_rx_callback *ext;
uint8_t num_tx;
uint8_t num_std;
uint8_t num_ext;
};
/**
* @brief Define Bosch M_CAN TX and RX callbacks
*
* This macro allows a Bosch M_CAN driver frontend using a fixed Message RAM configuration to limit
* the required software resources (e.g. limit the number of the standard (11-bit) or extended
* (29-bit) filters in use).
*
* Frontend drivers supporting dynamic Message RAM configuration should use @ref
* CAN_MCAN_DT_CALLBACKS_DEFINE() or @ref CAN_MCAN_DT_INST_CALLBACKS_DEFINE() instead.
*
* @param _name callbacks variable name
* @param _tx Number of Tx callbacks
* @param _std Number of standard (11-bit) filter callbacks
* @param _ext Number of extended (29-bit) filter callbacks
* @see CAN_MCAN_DT_CALLBACKS_DEFINE()
*/
#define CAN_MCAN_CALLBACKS_DEFINE(_name, _tx, _std, _ext) \
static struct can_mcan_tx_callback _name##_tx_cbs[_tx]; \
static struct can_mcan_rx_callback _name##_std_cbs[_std]; \
static struct can_mcan_rx_callback _name##_ext_cbs[_ext]; \
static const struct can_mcan_callbacks _name = { \
.tx = _name##_tx_cbs, \
.std = _name##_std_cbs, \
.ext = _name##_ext_cbs, \
.num_tx = _tx, \
.num_std = _std, \
.num_ext = _ext, \
}
/**
* @brief Define Bosch M_CAN TX and RX callbacks
* @param node_id node identifier
* @param _name callbacks variable name
* @see CAN_MCAN_CALLBACKS_DEFINE()
*/
#define CAN_MCAN_DT_CALLBACKS_DEFINE(node_id, _name) \
CAN_MCAN_CALLBACKS_DEFINE(_name, CAN_MCAN_DT_MRAM_TX_BUFFER_ELEMENTS(node_id), \
CAN_MCAN_DT_MRAM_STD_FILTER_ELEMENTS(node_id), \
CAN_MCAN_DT_MRAM_EXT_FILTER_ELEMENTS(node_id))
/**
* @brief Equivalent to CAN_MCAN_DT_CALLBACKS_DEFINE(DT_DRV_INST(inst))
* @param inst DT_DRV_COMPAT instance number
* @param _name callbacks variable name
* @see CAN_MCAN_DT_CALLBACKS_DEFINE()
*/
#define CAN_MCAN_DT_INST_CALLBACKS_DEFINE(inst, _name) \
CAN_MCAN_DT_CALLBACKS_DEFINE(DT_DRV_INST(inst), _name)
struct can_mcan_config {
struct can_mcan_ops *ops;
const struct can_mcan_ops *ops;
const struct can_mcan_callbacks *callbacks;
uint16_t mram_elements[CAN_MCAN_MRAM_CFG_NUM_CELLS];
uint16_t mram_offsets[CAN_MCAN_MRAM_CFG_NUM_CELLS];
size_t mram_size;
uint32_t bus_speed;
uint16_t sjw;
uint16_t sample_point;
@ -834,17 +1133,62 @@ struct can_mcan_config {
const void *custom;
};
/**
* @brief Get an array containing the number of elements in Bosch M_CAN Message RAM
*
* The order of the array entries is given by the @ref CAN_MCAN_MRAM_CFG definitions.
*
* @param node_id node identifier
* @return array of number of elements
*/
#define CAN_MCAN_DT_MRAM_ELEMENTS_GET(node_id) \
{ \
0, /* offset cell */ \
CAN_MCAN_DT_MRAM_STD_FILTER_ELEMENTS(node_id), \
CAN_MCAN_DT_MRAM_EXT_FILTER_ELEMENTS(node_id), \
CAN_MCAN_DT_MRAM_RX_FIFO0_ELEMENTS(node_id), \
CAN_MCAN_DT_MRAM_RX_FIFO1_ELEMENTS(node_id), \
CAN_MCAN_DT_MRAM_RX_BUFFER_ELEMENTS(node_id), \
CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEMENTS(node_id), \
CAN_MCAN_DT_MRAM_TX_BUFFER_ELEMENTS(node_id) \
}
/**
* @brief Get an array containing the base offsets for element in Bosch M_CAN Message RAM
*
* The order of the array entries is given by the @ref CAN_MCAN_MRAM_CFG definitions.
*
* @param node_id node identifier
* @return array of base offsets for elements
*/
#define CAN_MCAN_DT_MRAM_OFFSETS_GET(node_id) \
{ \
0, /* offset cell */ \
CAN_MCAN_DT_MRAM_STD_FILTER_OFFSET(node_id), \
CAN_MCAN_DT_MRAM_EXT_FILTER_OFFSET(node_id), \
CAN_MCAN_DT_MRAM_RX_FIFO0_OFFSET(node_id), \
CAN_MCAN_DT_MRAM_RX_FIFO1_OFFSET(node_id), \
CAN_MCAN_DT_MRAM_RX_BUFFER_OFFSET(node_id), \
CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_OFFSET(node_id), \
CAN_MCAN_DT_MRAM_TX_BUFFER_OFFSET(node_id) \
}
/**
* @brief Static initializer for @p can_mcan_config struct
*
* @param node_id Devicetree node identifier
* @param _custom Pointer to custom driver frontend configuration structure
* @param _ops Pointer to front-end @a can_mcan_ops
* @param _cbs Pointer to front-end @a can_mcan_callbacks
*/
#ifdef CONFIG_CAN_FD_MODE
#define CAN_MCAN_DT_CONFIG_GET(node_id, _custom, _ops) \
#define CAN_MCAN_DT_CONFIG_GET(node_id, _custom, _ops, _cbs) \
{ \
.ops = _ops, \
.callbacks = _cbs, \
.mram_elements = CAN_MCAN_DT_MRAM_ELEMENTS_GET(node_id), \
.mram_offsets = CAN_MCAN_DT_MRAM_OFFSETS_GET(node_id), \
.mram_size = CAN_MCAN_DT_MRAM_ELEMENTS_SIZE(node_id), \
.bus_speed = DT_PROP(node_id, bus_speed), \
.sjw = DT_PROP(node_id, sjw), \
.sample_point = DT_PROP_OR(node_id, sample_point, 0), \
@ -862,9 +1206,13 @@ struct can_mcan_config {
.custom = _custom, \
}
#else /* CONFIG_CAN_FD_MODE */
#define CAN_MCAN_DT_CONFIG_GET(node_id, _custom, _ops) \
#define CAN_MCAN_DT_CONFIG_GET(node_id, _custom, _ops, _cbs) \
{ \
.ops = _ops, \
.callbacks = _cbs, \
.mram_elements = CAN_MCAN_DT_MRAM_ELEMENTS_GET(node_id), \
.mram_offsets = CAN_MCAN_DT_MRAM_OFFSETS_GET(node_id), \
.mram_size = CAN_MCAN_DT_MRAM_ELEMENTS_SIZE(node_id), \
.bus_speed = DT_PROP(node_id, bus_speed), \
.sjw = DT_PROP(node_id, sjw), \
.sample_point = DT_PROP_OR(node_id, sample_point, 0), \
@ -882,14 +1230,14 @@ struct can_mcan_config {
* @param inst DT_DRV_COMPAT instance number
* @param _custom Pointer to custom driver frontend configuration structure
* @param _ops Pointer to front-end @a can_mcan_ops
* @param _cbs Pointer to front-end @a can_mcan_callbacks
* @see CAN_MCAN_DT_CONFIG_GET()
*/
#define CAN_MCAN_DT_CONFIG_INST_GET(inst, _custom, _ops) \
CAN_MCAN_DT_CONFIG_GET(DT_DRV_INST(inst), _custom, _ops)
#define CAN_MCAN_DT_CONFIG_INST_GET(inst, _custom, _ops, _cbs) \
CAN_MCAN_DT_CONFIG_GET(DT_DRV_INST(inst), _custom, _ops, _cbs)
/**
* @brief Initializer for a @a can_mcan_data struct
* @param _msg_ram Pointer to message RAM structure
* @param _custom Pointer to custom driver frontend data structure
*/
#define CAN_MCAN_DATA_INITIALIZER(_custom) \

View file

@ -23,16 +23,13 @@ LOG_MODULE_REGISTER(can_mcux_mcan, CONFIG_CAN_LOG_LEVEL);
struct mcux_mcan_config {
mm_reg_t base;
mem_addr_t mram;
const struct device *clock_dev;
clock_control_subsys_t clock_subsys;
void (*irq_config_func)(const struct device *dev);
const struct pinctrl_dev_config *pincfg;
};
struct mcux_mcan_data {
struct can_mcan_msg_sram msg_ram __nocache;
};
static int mcux_mcan_read_reg(const struct device *dev, uint16_t reg, uint32_t *val)
{
const struct can_mcan_config *mcan_config = dev->config;
@ -51,27 +48,27 @@ static int mcux_mcan_write_reg(const struct device *dev, uint16_t reg, uint32_t
static int mcux_mcan_read_mram(const struct device *dev, uint16_t offset, void *dst, size_t len)
{
struct can_mcan_data *mcan_data = dev->data;
struct mcux_mcan_data *mcux_data = mcan_data->custom;
const struct can_mcan_config *mcan_config = dev->config;
const struct mcux_mcan_config *mcux_config = mcan_config->custom;
return can_mcan_sys_read_mram(POINTER_TO_UINT(&mcux_data->msg_ram), offset, dst, len);
return can_mcan_sys_read_mram(mcux_config->mram, offset, dst, len);
}
static int mcux_mcan_write_mram(const struct device *dev, uint16_t offset, const void *src,
size_t len)
{
struct can_mcan_data *mcan_data = dev->data;
struct mcux_mcan_data *mcux_data = mcan_data->custom;
const struct can_mcan_config *mcan_config = dev->config;
const struct mcux_mcan_config *mcux_config = mcan_config->custom;
return can_mcan_sys_write_mram(POINTER_TO_UINT(&mcux_data->msg_ram), offset, src, len);
return can_mcan_sys_write_mram(mcux_config->mram, offset, src, len);
}
static int mcux_mcan_clear_mram(const struct device *dev, uint16_t offset, size_t len)
{
struct can_mcan_data *mcan_data = dev->data;
struct mcux_mcan_data *mcux_data = mcan_data->custom;
const struct can_mcan_config *mcan_config = dev->config;
const struct mcux_mcan_config *mcux_config = mcan_config->custom;
return can_mcan_sys_clear_mram(POINTER_TO_UINT(&mcux_data->msg_ram), offset, len);
return can_mcan_sys_clear_mram(mcux_config->mram, offset, len);
}
static int mcux_mcan_get_core_clock(const struct device *dev, uint32_t *rate)
@ -87,9 +84,7 @@ static int mcux_mcan_init(const struct device *dev)
{
const struct can_mcan_config *mcan_config = dev->config;
const struct mcux_mcan_config *mcux_config = mcan_config->custom;
struct can_mcan_data *mcan_data = dev->data;
struct mcux_mcan_data *mcux_data = mcan_data->custom;
const uintptr_t mrba = POINTER_TO_UINT(&mcux_data->msg_ram) & MCUX_MCAN_MRBA_BA;
const uintptr_t mrba = mcux_config->mram & MCUX_MCAN_MRBA_BA;
int err;
if (!device_is_ready(mcux_config->clock_dev)) {
@ -113,7 +108,7 @@ static int mcux_mcan_init(const struct device *dev)
return -EIO;
}
err = can_mcan_configure_mram(dev, mrba, POINTER_TO_UINT(&mcux_data->msg_ram));
err = can_mcan_configure_mram(dev, mrba, mcux_config->mram);
if (err != 0) {
return -EIO;
}
@ -204,12 +199,17 @@ static const struct can_mcan_ops mcux_mcan_ops = {
};
#define MCUX_MCAN_INIT(n) \
CAN_MCAN_DT_INST_BUILD_ASSERT_MRAM_CFG(n); \
PINCTRL_DT_INST_DEFINE(n); \
\
static void mcux_mcan_irq_config_##n(const struct device *dev); \
\
CAN_MCAN_DT_INST_CALLBACKS_DEFINE(n, mcux_mcan_cbs_##n); \
CAN_MCAN_DT_INST_MRAM_DEFINE(n, mcux_mcan_mram_##n); \
\
static const struct mcux_mcan_config mcux_mcan_config_##n = { \
.base = (mm_reg_t)DT_INST_REG_ADDR(n), \
.base = CAN_MCAN_DT_INST_MCAN_ADDR(n), \
.mram = (mem_addr_t)POINTER_TO_UINT(&mcux_mcan_mram_##n), \
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
.clock_subsys = (clock_control_subsys_t) \
DT_INST_CLOCKS_CELL(n, name), \
@ -219,12 +219,11 @@ static const struct can_mcan_ops mcux_mcan_ops = {
\
static const struct can_mcan_config can_mcan_config_##n = \
CAN_MCAN_DT_CONFIG_INST_GET(n, &mcux_mcan_config_##n, \
&mcux_mcan_ops); \
\
static struct mcux_mcan_data mcux_mcan_data_##n; \
&mcux_mcan_ops, \
&mcux_mcan_cbs_##n); \
\
static struct can_mcan_data can_mcan_data_##n = \
CAN_MCAN_DATA_INITIALIZER(&mcux_mcan_data_##n); \
CAN_MCAN_DATA_INITIALIZER(NULL); \
\
DEVICE_DT_INST_DEFINE(n, &mcux_mcan_init, NULL, \
&can_mcan_data_##n, \

View file

@ -21,16 +21,13 @@ LOG_MODULE_REGISTER(can_sam, CONFIG_CAN_LOG_LEVEL);
struct can_sam_config {
mm_reg_t base;
mem_addr_t mram;
void (*config_irq)(void);
const struct atmel_sam_pmc_config clock_cfg;
const struct pinctrl_dev_config *pcfg;
int divider;
};
struct can_sam_data {
struct can_mcan_msg_sram msg_ram;
};
static int can_sam_read_reg(const struct device *dev, uint16_t reg, uint32_t *val)
{
const struct can_mcan_config *mcan_config = dev->config;
@ -49,27 +46,27 @@ static int can_sam_write_reg(const struct device *dev, uint16_t reg, uint32_t va
static int can_sam_read_mram(const struct device *dev, uint16_t offset, void *dst, size_t len)
{
struct can_mcan_data *mcan_data = dev->data;
struct can_sam_data *sam_data = mcan_data->custom;
const struct can_mcan_config *mcan_config = dev->config;
const struct can_sam_config *sam_config = mcan_config->custom;
return can_mcan_sys_read_mram(POINTER_TO_UINT(&sam_data->msg_ram), offset, dst, len);
return can_mcan_sys_read_mram(sam_config->mram, offset, dst, len);
}
static int can_sam_write_mram(const struct device *dev, uint16_t offset, const void *src,
size_t len)
{
struct can_mcan_data *mcan_data = dev->data;
struct can_sam_data *sam_data = mcan_data->custom;
const struct can_mcan_config *mcan_config = dev->config;
const struct can_sam_config *sam_config = mcan_config->custom;
return can_mcan_sys_write_mram(POINTER_TO_UINT(&sam_data->msg_ram), offset, src, len);
return can_mcan_sys_write_mram(sam_config->mram, offset, src, len);
}
static int can_sam_clear_mram(const struct device *dev, uint16_t offset, size_t len)
{
struct can_mcan_data *mcan_data = dev->data;
struct can_sam_data *sam_data = mcan_data->custom;
const struct can_mcan_config *mcan_config = dev->config;
const struct can_sam_config *sam_config = mcan_config->custom;
return can_mcan_sys_clear_mram(POINTER_TO_UINT(&sam_data->msg_ram), offset, len);
return can_mcan_sys_clear_mram(sam_config->mram, offset, len);
}
static int can_sam_get_core_clock(const struct device *dev, uint32_t *rate)
@ -96,8 +93,6 @@ static int can_sam_init(const struct device *dev)
{
const struct can_mcan_config *mcan_cfg = dev->config;
const struct can_sam_config *sam_cfg = mcan_cfg->custom;
struct can_mcan_data *mcan_data = dev->data;
struct can_sam_data *sam_data = mcan_data->custom;
int ret;
can_sam_clock_enable(sam_cfg);
@ -107,7 +102,7 @@ static int can_sam_init(const struct device *dev)
return ret;
}
ret = can_mcan_configure_mram(dev, 0U, POINTER_TO_UINT(&sam_data->msg_ram));
ret = can_mcan_configure_mram(dev, 0U, sam_cfg->mram);
if (ret != 0) {
return ret;
}
@ -195,8 +190,12 @@ static void config_can_##inst##_irq(void)
}
#define CAN_SAM_CFG_INST(inst) \
CAN_MCAN_DT_INST_CALLBACKS_DEFINE(inst, can_sam_cbs_##inst); \
CAN_MCAN_DT_INST_MRAM_DEFINE(inst, can_sam_mram_##inst); \
\
static const struct can_sam_config can_sam_cfg_##inst = { \
.base = (mm_reg_t)DT_INST_REG_ADDR(inst), \
.base = CAN_MCAN_DT_INST_MCAN_ADDR(inst), \
.mram = (mem_addr_t)POINTER_TO_UINT(&can_sam_mram_##inst), \
.clock_cfg = SAM_DT_INST_CLOCK_PMC_CFG(inst), \
.divider = DT_INST_PROP(inst, divider), \
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
@ -205,13 +204,12 @@ static void config_can_##inst##_irq(void)
\
static const struct can_mcan_config can_mcan_cfg_##inst = \
CAN_MCAN_DT_CONFIG_INST_GET(inst, &can_sam_cfg_##inst, \
&can_sam_ops);
&can_sam_ops, \
&can_sam_cbs_##inst);
#define CAN_SAM_DATA_INST(inst) \
static struct can_sam_data can_sam_data_##inst; \
\
static struct can_mcan_data can_mcan_data_##inst = \
CAN_MCAN_DATA_INITIALIZER(&can_sam_data_##inst);
CAN_MCAN_DATA_INITIALIZER(NULL);
#define CAN_SAM_DEVICE_INST(inst) \
DEVICE_DT_INST_DEFINE(inst, &can_sam_init, NULL, \
@ -221,6 +219,7 @@ static void config_can_##inst##_irq(void)
&can_sam_driver_api);
#define CAN_SAM_INST(inst) \
CAN_MCAN_DT_INST_BUILD_ASSERT_MRAM_CFG(inst); \
PINCTRL_DT_INST_DEFINE(inst); \
CAN_SAM_IRQ_CFG_FUNCTION(inst) \
CAN_SAM_CFG_INST(inst) \

View file

@ -21,6 +21,7 @@ LOG_MODULE_REGISTER(can_sam0, CONFIG_CAN_LOG_LEVEL);
struct can_sam0_config {
mm_reg_t base;
mem_addr_t mram;
void (*config_irq)(void);
const struct pinctrl_dev_config *pcfg;
volatile uint32_t *mclk;
@ -29,10 +30,6 @@ struct can_sam0_config {
int divider;
};
struct can_sam0_data {
struct can_mcan_msg_sram msg_ram;
};
static int can_sam0_read_reg(const struct device *dev, uint16_t reg, uint32_t *val)
{
const struct can_mcan_config *mcan_config = dev->config;
@ -65,27 +62,27 @@ static int can_sam0_write_reg(const struct device *dev, uint16_t reg, uint32_t v
static int can_sam0_read_mram(const struct device *dev, uint16_t offset, void *dst, size_t len)
{
struct can_mcan_data *mcan_data = dev->data;
struct can_sam0_data *sam_data = mcan_data->custom;
const struct can_mcan_config *mcan_config = dev->config;
const struct can_sam0_config *sam_config = mcan_config->custom;
return can_mcan_sys_read_mram(POINTER_TO_UINT(&sam_data->msg_ram), offset, dst, len);
return can_mcan_sys_read_mram(sam_config->mram, offset, dst, len);
}
static int can_sam0_write_mram(const struct device *dev, uint16_t offset, const void *src,
size_t len)
{
struct can_mcan_data *mcan_data = dev->data;
struct can_sam0_data *sam_data = mcan_data->custom;
const struct can_mcan_config *mcan_config = dev->config;
const struct can_sam0_config *sam_config = mcan_config->custom;
return can_mcan_sys_write_mram(POINTER_TO_UINT(&sam_data->msg_ram), offset, src, len);
return can_mcan_sys_write_mram(sam_config->mram, offset, src, len);
}
static int can_sam0_clear_mram(const struct device *dev, uint16_t offset, size_t len)
{
struct can_mcan_data *mcan_data = dev->data;
struct can_sam0_data *sam_data = mcan_data->custom;
const struct can_mcan_config *mcan_config = dev->config;
const struct can_sam0_config *sam_config = mcan_config->custom;
return can_mcan_sys_clear_mram(POINTER_TO_UINT(&sam_data->msg_ram), offset, len);
return can_mcan_sys_clear_mram(sam_config->mram, offset, len);
}
void can_sam0_line_x_isr(const struct device *dev)
@ -123,8 +120,6 @@ static int can_sam0_init(const struct device *dev)
{
const struct can_mcan_config *mcan_cfg = dev->config;
const struct can_sam0_config *sam_cfg = mcan_cfg->custom;
struct can_mcan_data *mcan_data = dev->data;
struct can_sam0_data *sam_data = mcan_data->custom;
int ret;
can_sam0_clock_enable(sam_cfg);
@ -135,7 +130,7 @@ static int can_sam0_init(const struct device *dev)
return ret;
}
ret = can_mcan_configure_mram(dev, 0U, POINTER_TO_UINT(&sam_data->msg_ram));
ret = can_mcan_configure_mram(dev, 0U, sam_cfg->mram);
if (ret != 0) {
LOG_ERR("failed to configure message ram");
return ret;
@ -221,8 +216,12 @@ static void config_can_##inst##_irq(void) \
}
#define CAN_SAM0_CFG_INST(inst) \
CAN_MCAN_DT_INST_CALLBACKS_DEFINE(inst, can_sam0_cbs_##inst); \
CAN_MCAN_DT_INST_MRAM_DEFINE(inst, can_sam0_mram_##inst); \
\
static const struct can_sam0_config can_sam0_cfg_##inst = { \
.base = (mm_reg_t)DT_INST_REG_ADDR(inst), \
.base = CAN_MCAN_DT_INST_MCAN_ADDR(inst), \
.mram = (mem_addr_t)POINTER_TO_UINT(&can_sam0_mram_##inst), \
.mclk = (volatile uint32_t *)MCLK_MASK_DT_INT_REG_ADDR(inst), \
.mclk_mask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(inst, mclk, bit)), \
.gclk_core_id = DT_INST_CLOCKS_CELL_BY_NAME(inst, gclk, periph_ch), \
@ -232,13 +231,12 @@ static void config_can_##inst##_irq(void) \
}; \
\
static const struct can_mcan_config can_mcan_cfg_##inst = \
CAN_MCAN_DT_CONFIG_INST_GET(inst, &can_sam0_cfg_##inst, &can_sam0_ops);
CAN_MCAN_DT_CONFIG_INST_GET(inst, &can_sam0_cfg_##inst, &can_sam0_ops, \
&can_sam0_cbs_##inst);
#define CAN_SAM0_DATA_INST(inst) \
static struct can_sam0_data can_sam0_data_##inst; \
\
static struct can_mcan_data can_mcan_data_##inst = \
CAN_MCAN_DATA_INITIALIZER(&can_sam0_data_##inst);
CAN_MCAN_DATA_INITIALIZER(NULL);
#define CAN_SAM0_DEVICE_INST(inst) \
DEVICE_DT_INST_DEFINE(inst, &can_sam0_init, NULL, \
@ -248,6 +246,7 @@ static void config_can_##inst##_irq(void) \
&can_sam0_driver_api);
#define CAN_SAM0_INST(inst) \
CAN_MCAN_DT_INST_BUILD_ASSERT_MRAM_CFG(inst); \
PINCTRL_DT_INST_DEFINE(inst); \
CAN_SAM0_IRQ_CFG_FUNCTION(inst) \
CAN_SAM0_CFG_INST(inst) \

View file

@ -635,14 +635,21 @@ static const struct can_mcan_ops can_stm32fd_ops = {
.clear_mram = can_stm32fd_clear_mram,
};
/* Assert that the Message RAM configuration matches the fixed hardware configuration */
BUILD_ASSERT(NUM_STD_FILTER_ELEMENTS == 28, "Standard filter elements must be 28");
BUILD_ASSERT(NUM_EXT_FILTER_ELEMENTS == 8, "Extended filter elements must be 8");
BUILD_ASSERT(NUM_RX_FIFO0_ELEMENTS == 3, "Rx FIFO 0 elements must be 3");
BUILD_ASSERT(NUM_RX_FIFO1_ELEMENTS == 3, "Rx FIFO 1 elements must be 3");
BUILD_ASSERT(NUM_RX_BUF_ELEMENTS == 0, "Rx Buffer elements must be 0");
BUILD_ASSERT(NUM_TX_EVENT_FIFO_ELEMENTS == 3, "Tx Event FIFO elements must be 3");
BUILD_ASSERT(NUM_TX_BUF_ELEMENTS == 3, "Tx Buffer elements must be 0");
#define CAN_STM32FD_BUILD_ASSERT_MRAM_CFG(inst) \
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_STD_FILTER_ELEMENTS(inst) == 28, \
"Standard filter elements must be 28"); \
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_EXT_FILTER_ELEMENTS(inst) == 8, \
"Extended filter elements must be 8"); \
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_RX_FIFO0_ELEMENTS(inst) == 3, \
"Rx FIFO 0 elements must be 3"); \
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_RX_FIFO1_ELEMENTS(inst) == 3, \
"Rx FIFO 1 elements must be 3"); \
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_RX_BUFFER_ELEMENTS(inst) == 0, \
"Rx Buffer elements must be 0"); \
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_TX_EVENT_FIFO_ELEMENTS(inst) == 3, \
"Tx Event FIFO elements must be 3"); \
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_TX_BUFFER_ELEMENTS(inst) == 3, \
"Tx Buffer elements must be 0");
#define CAN_STM32FD_IRQ_CFG_FUNCTION(inst) \
static void config_can_##inst##_irq(void) \
@ -659,13 +666,22 @@ static void config_can_##inst##_irq(void) \
}
#define CAN_STM32FD_CFG_INST(inst) \
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_ELEMENTS_SIZE(inst) <= \
CAN_MCAN_DT_INST_MRAM_SIZE(inst), \
"Insufficient Message RAM size to hold elements"); \
\
PINCTRL_DT_INST_DEFINE(inst); \
CAN_MCAN_CALLBACKS_DEFINE(can_stm32fd_cbs_##inst, \
CAN_MCAN_DT_INST_MRAM_TX_BUFFER_ELEMENTS(inst), \
CONFIG_CAN_MAX_STD_ID_FILTER, \
CONFIG_CAN_MAX_EXT_ID_FILTER); \
\
static const struct stm32_pclken can_stm32fd_pclken_##inst[] = \
STM32_DT_INST_CLOCKS(inst); \
\
static const struct can_stm32fd_config can_stm32fd_cfg_##inst = { \
.base = (mm_reg_t)DT_INST_REG_ADDR_BY_NAME(inst, m_can), \
.mram = (mem_addr_t)DT_INST_REG_ADDR_BY_NAME(inst, message_ram), \
.base = CAN_MCAN_DT_INST_MCAN_ADDR(inst), \
.mram = CAN_MCAN_DT_INST_MRAM_ADDR(inst), \
.pclken = can_stm32fd_pclken_##inst, \
.pclk_len = DT_INST_NUM_CLOCKS(inst), \
.config_irq = config_can_##inst##_irq, \
@ -675,7 +691,8 @@ static void config_can_##inst##_irq(void) \
\
static const struct can_mcan_config can_mcan_cfg_##inst = \
CAN_MCAN_DT_CONFIG_INST_GET(inst, &can_stm32fd_cfg_##inst, \
&can_stm32fd_ops);
&can_stm32fd_ops, \
&can_stm32fd_cbs_##inst);
#define CAN_STM32FD_DATA_INST(inst) \
static struct can_mcan_data can_mcan_data_##inst = \
@ -687,10 +704,11 @@ static void config_can_##inst##_irq(void) \
POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \
&can_stm32fd_driver_api);
#define CAN_STM32FD_INST(inst) \
CAN_STM32FD_IRQ_CFG_FUNCTION(inst) \
CAN_STM32FD_CFG_INST(inst) \
CAN_STM32FD_DATA_INST(inst) \
#define CAN_STM32FD_INST(inst) \
CAN_STM32FD_BUILD_ASSERT_MRAM_CFG(inst) \
CAN_STM32FD_IRQ_CFG_FUNCTION(inst) \
CAN_STM32FD_CFG_INST(inst) \
CAN_STM32FD_DATA_INST(inst) \
CAN_STM32FD_DEVICE_INST(inst)
DT_INST_FOREACH_STATUS_OKAY(CAN_STM32FD_INST)

View file

@ -215,13 +215,19 @@ static const struct can_mcan_ops can_stm32h7_ops = {
};
#define CAN_STM32H7_MCAN_INIT(n) \
CAN_MCAN_DT_INST_BUILD_ASSERT_MRAM_CFG(n); \
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_ELEMENTS_SIZE(n) <= \
CAN_MCAN_DT_INST_MRAM_SIZE(n), \
"Insufficient Message RAM size to hold elements"); \
\
static void stm32h7_mcan_irq_config_##n(void); \
\
PINCTRL_DT_INST_DEFINE(n); \
CAN_MCAN_DT_INST_CALLBACKS_DEFINE(n, can_stm32h7_cbs_##n); \
\
static const struct can_stm32h7_config can_stm32h7_cfg_##n = { \
.base = (mm_reg_t)DT_INST_REG_ADDR_BY_NAME(n, m_can), \
.mram = (mem_addr_t)DT_INST_REG_ADDR_BY_NAME(n, message_ram), \
.base = CAN_MCAN_DT_INST_MCAN_ADDR(n), \
.mram = CAN_MCAN_DT_INST_MRAM_ADDR(n), \
.config_irq = stm32h7_mcan_irq_config_##n, \
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
.pclken = { \
@ -232,7 +238,8 @@ static const struct can_mcan_ops can_stm32h7_ops = {
\
static const struct can_mcan_config can_mcan_cfg_##n = \
CAN_MCAN_DT_CONFIG_INST_GET(n, &can_stm32h7_cfg_##n, \
&can_stm32h7_ops); \
&can_stm32h7_ops, \
&can_stm32h7_cbs_##n); \
\
static struct can_mcan_data can_mcan_data_##n = \
CAN_MCAN_DATA_INITIALIZER(NULL); \