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) int can_mcan_stop(const struct device *dev)
{ {
const struct can_mcan_config *config = dev->config; 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_data *data = dev->data;
can_tx_callback_t tx_cb; can_tx_callback_t tx_cb;
uint32_t tx_idx; uint32_t tx_idx;
@ -370,12 +371,12 @@ int can_mcan_stop(const struct device *dev)
data->started = false; data->started = false;
for (tx_idx = 0U; tx_idx < ARRAY_SIZE(data->tx_fin_cb); tx_idx++) { for (tx_idx = 0U; tx_idx < cbs->num_tx; tx_idx++) {
tx_cb = data->tx_fin_cb[tx_idx]; tx_cb = cbs->tx[tx_idx].function;
if (tx_cb != NULL) { if (tx_cb != NULL) {
data->tx_fin_cb[tx_idx] = NULL; cbs->tx[tx_idx].function = NULL;
tx_cb(dev, -ENETDOWN, data->tx_fin_cb_arg[tx_idx]); tx_cb(dev, -ENETDOWN, cbs->tx[tx_idx].user_data);
k_sem_give(&data->tx_sem); 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) 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_data *data = dev->data;
struct can_mcan_tx_event_fifo tx_event; struct can_mcan_tx_event_fifo tx_event;
can_tx_callback_t tx_cb; 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) { while ((txefs & CAN_MCAN_TXEFS_EFFL) != 0U) {
event_idx = FIELD_GET(CAN_MCAN_TXEFS_EFGI, txefs); 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), event_idx * sizeof(struct can_mcan_tx_event_fifo),
&tx_event, &tx_event,
sizeof(struct can_mcan_tx_event_fifo)); 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); k_sem_give(&data->tx_sem);
tx_cb = data->tx_fin_cb[tx_idx]; __ASSERT_NO_MSG(tx_idx <= cbs->num_tx);
data->tx_fin_cb[tx_idx] = NULL; tx_cb = cbs->tx[tx_idx].function;
tx_cb(dev, 0, data->tx_fin_cb_arg[tx_idx]); 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); err = can_mcan_read_reg(dev, CAN_MCAN_TXEFS, &txefs);
if (err != 0) { 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, static void can_mcan_get_message(const struct device *dev, uint16_t fifo_offset,
uint16_t fifo_status_reg, uint16_t fifo_ack_reg) uint16_t fifo_status_reg, uint16_t fifo_ack_reg)
{ {
struct can_mcan_data *data = dev->data; const struct can_mcan_config *config = dev->config;
uint32_t get_idx, filt_idx; const struct can_mcan_callbacks *cbs = config->callbacks;
struct can_mcan_rx_fifo_hdr hdr;
struct can_frame frame = {0}; struct can_frame frame = {0};
can_rx_callback_t cb; can_rx_callback_t cb;
void *user_data;
uint8_t flags;
uint32_t get_idx;
uint32_t filt_idx;
int data_length; 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; uint32_t fifo_status;
int err; int err;
@ -630,25 +635,25 @@ static void can_mcan_get_message(const struct device *dev, uint16_t fifo_offset,
if (hdr.xtd != 0) { if (hdr.xtd != 0) {
frame.id = hdr.ext_id; frame.id = hdr.ext_id;
frame.flags |= CAN_FRAME_IDE; frame.flags |= CAN_FRAME_IDE;
rtr_filter_mask = (data->ext_filt_rtr_mask & BIT(filt_idx)) != 0U; flags = cbs->ext[filt_idx].flags;
rtr_filter = (data->ext_filt_rtr & BIT(filt_idx)) != 0;
fd_frame_filter = (data->ext_filt_fd_frame & BIT(filt_idx)) != 0U;
} else { } else {
frame.id = hdr.std_id; frame.id = hdr.std_id;
rtr_filter_mask = (data->std_filt_rtr_mask & BIT(filt_idx)) != 0U; flags = cbs->std[filt_idx].flags;
rtr_filter = (data->std_filt_rtr & BIT(filt_idx)) != 0;
fd_frame_filter = (data->std_filt_fd_frame & BIT(filt_idx)) != 0U;
} }
if (rtr_filter_mask && (rtr_filter != ((frame.flags & CAN_FRAME_RTR) != 0U))) { if (((frame.flags & CAN_FRAME_RTR) == 0U && (flags & CAN_FILTER_DATA) == 0U) ||
/* RTR bit does not match filter RTR mask, drop frame */ ((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); err = can_mcan_write_reg(dev, fifo_ack_reg, get_idx);
if (err != 0) { if (err != 0) {
return; return;
} }
goto ack; 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); err = can_mcan_write_reg(dev, fifo_ack_reg, get_idx);
if (err != 0) { if (err != 0) {
return; 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) { if ((frame.flags & CAN_FRAME_IDE) != 0) {
LOG_DBG("Frame on filter %d, ID: 0x%x", LOG_DBG("Frame on filter %d, ID: 0x%x",
filt_idx + NUM_STD_FILTER_DATA, frame.id); filt_idx + cbs->num_std, frame.id);
cb = data->rx_cb_ext[filt_idx]; __ASSERT_NO_MSG(filt_idx <= cbs->num_ext);
cb_arg = data->cb_arg_ext[filt_idx]; cb = cbs->ext[filt_idx].function;
user_data = cbs->ext[filt_idx].user_data;
} else { } else {
LOG_DBG("Frame on filter %d, ID: 0x%x", filt_idx, frame.id); LOG_DBG("Frame on filter %d, ID: 0x%x", filt_idx, frame.id);
cb = data->rx_cb_std[filt_idx]; __ASSERT_NO_MSG(filt_idx <= cbs->num_std);
cb_arg = data->cb_arg_std[filt_idx]; cb = cbs->std[filt_idx].function;
user_data = cbs->std[filt_idx].user_data;
} }
if (cb) { if (cb) {
cb(dev, &frame, cb_arg); cb(dev, &frame, user_data);
} else { } else {
LOG_DBG("cb missing"); LOG_DBG("cb missing");
} }
@ -703,6 +710,7 @@ ack:
void can_mcan_line_1_isr(const struct device *dev) void can_mcan_line_1_isr(const struct device *dev)
{ {
const struct can_mcan_config *config = dev->config;
const uint32_t events = const uint32_t events =
CAN_MCAN_IR_RF0N | CAN_MCAN_IR_RF1N | CAN_MCAN_IR_RF0L | CAN_MCAN_IR_RF1L; CAN_MCAN_IR_RF0N | CAN_MCAN_IR_RF1N | CAN_MCAN_IR_RF0L | CAN_MCAN_IR_RF1L;
uint32_t ir; uint32_t ir;
@ -716,14 +724,14 @@ void can_mcan_line_1_isr(const struct device *dev)
while ((ir & events) != 0U) { while ((ir & events) != 0U) {
if ((ir & CAN_MCAN_IR_RF0N) != 0U) { if ((ir & CAN_MCAN_IR_RF0N) != 0U) {
LOG_DBG("RX FIFO0 INT"); LOG_DBG("RX FIFO0 INT");
can_mcan_get_message(dev, CAN_MCAN_MRAM_OFFSET_RX_FIFO0, CAN_MCAN_RXF0S, can_mcan_get_message(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_RX_FIFO0],
CAN_MCAN_RXF0A); CAN_MCAN_RXF0S, CAN_MCAN_RXF0A);
} }
if ((ir & CAN_MCAN_IR_RF1N) != 0U) { if ((ir & CAN_MCAN_IR_RF1N) != 0U) {
LOG_DBG("RX FIFO1 INT"); LOG_DBG("RX FIFO1 INT");
can_mcan_get_message(dev, CAN_MCAN_MRAM_OFFSET_RX_FIFO1, CAN_MCAN_RXF1S, can_mcan_get_message(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_RX_FIFO1],
CAN_MCAN_RXF1A); CAN_MCAN_RXF1S, CAN_MCAN_RXF1A);
} }
if ((ir & CAN_MCAN_IR_RF0L) != 0U) { 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, 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) 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; struct can_mcan_data *data = dev->data;
size_t data_length = can_dlc_to_bytes(frame->dlc); size_t data_length = can_dlc_to_bytes(frame->dlc);
struct can_mcan_tx_buffer_hdr tx_hdr = { 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; 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) + sizeof(struct can_mcan_tx_buffer) +
offsetof(struct can_mcan_tx_buffer, hdr), offsetof(struct can_mcan_tx_buffer, hdr),
&tx_hdr, sizeof(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; 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) + sizeof(struct can_mcan_tx_buffer) +
offsetof(struct can_mcan_tx_buffer, data_32), offsetof(struct can_mcan_tx_buffer, data_32),
&frame->data_32, ROUND_UP(data_length, sizeof(uint32_t))); &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; return err;
} }
data->tx_fin_cb[put_idx] = callback; __ASSERT_NO_MSG(put_idx <= cbs->num_tx);
data->tx_fin_cb_arg[put_idx] = user_data; 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)); err = can_mcan_write_reg(dev, CAN_MCAN_TXBAR, BIT(put_idx));
if (err != 0) { if (err != 0) {
@ -935,12 +946,14 @@ unlock:
static int can_mcan_get_free_std(const struct device *dev) 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; struct can_mcan_std_filter filter;
int err; int err;
int i; int i;
for (i = 0; i < NUM_STD_FILTER_DATA; ++i) { for (i = 0; i < cbs->num_std; ++i) {
err = can_mcan_read_mram(dev, CAN_MCAN_MRAM_OFFSET_STD_FILTER + err = can_mcan_read_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_STD_FILTER] +
i * sizeof(struct can_mcan_std_filter), &filter, i * sizeof(struct can_mcan_std_filter), &filter,
sizeof(struct can_mcan_std_filter)); sizeof(struct can_mcan_std_filter));
if (err != 0) { 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) 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) { if (ide) {
return NUM_EXT_FILTER_DATA; return cbs->num_ext;
} else { } 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, int can_mcan_add_rx_filter_std(const struct device *dev, can_rx_callback_t callback,
void *user_data, const struct can_filter *filter) 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_data *data = dev->data;
struct can_mcan_std_filter filter_element = { struct can_mcan_std_filter filter_element = {
.id1 = filter->id, .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 */ /* TODO proper fifo balancing */
filter_element.sfce = filter_id & 0x01 ? CAN_MCAN_FCE_FIFO1 : CAN_MCAN_FCE_FIFO0; 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_id * sizeof(struct can_mcan_std_filter),
&filter_element, sizeof(filter_element)); &filter_element, sizeof(filter_element));
if (err != 0) { 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); LOG_DBG("Attached std filter at %d", filter_id);
if ((filter->flags & CAN_FILTER_RTR) != 0U) { __ASSERT_NO_MSG(filter_id <= cbs->num_std);
data->std_filt_rtr |= (1U << filter_id); cbs->std[filter_id].function = callback;
} else { cbs->std[filter_id].user_data = user_data;
data->std_filt_rtr &= ~(1U << filter_id); cbs->std[filter_id].flags = filter->flags;
}
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;
return filter_id; return filter_id;
} }
static int can_mcan_get_free_ext(const struct device *dev) 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; struct can_mcan_ext_filter filter;
int err; int err;
int i; int i;
for (i = 0; i < NUM_EXT_FILTER_DATA; ++i) { for (i = 0; i < cbs->num_ext; ++i) {
err = can_mcan_read_mram(dev, CAN_MCAN_MRAM_OFFSET_EXT_FILTER + err = can_mcan_read_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_EXT_FILTER] +
i * sizeof(struct can_mcan_ext_filter), &filter, i * sizeof(struct can_mcan_ext_filter), &filter,
sizeof(struct can_mcan_ext_filter)); sizeof(struct can_mcan_ext_filter));
if (err != 0) { 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, 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) 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_data *data = dev->data;
struct can_mcan_ext_filter filter_element = { struct can_mcan_ext_filter filter_element = {
.id2 = filter->mask, .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 */ /* TODO proper fifo balancing */
filter_element.efce = filter_id & 0x01 ? CAN_MCAN_FCE_FIFO1 : CAN_MCAN_FCE_FIFO0; 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_id * sizeof(struct can_mcan_ext_filter),
&filter_element, sizeof(filter_element)); &filter_element, sizeof(filter_element));
if (err != 0) { 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); LOG_DBG("Attached ext filter at %d", filter_id);
if ((filter->flags & CAN_FILTER_RTR) != 0U) { __ASSERT_NO_MSG(filter_id <= cbs->num_ext);
data->ext_filt_rtr |= (1U << filter_id); cbs->ext[filter_id].function = callback;
} else { cbs->ext[filter_id].user_data = user_data;
data->ext_filt_rtr &= ~(1U << filter_id); cbs->ext[filter_id].flags = filter->flags;
}
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;
return filter_id; 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, 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_filter *filter)
{ {
const struct can_mcan_config *config = dev->config;
const struct can_mcan_callbacks *cbs = config->callbacks;
int filter_id; int filter_id;
if (callback == NULL) { 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) { if ((filter->flags & CAN_FILTER_IDE) != 0U) {
filter_id = can_mcan_add_rx_filter_ext(dev, callback, user_data, filter); filter_id = can_mcan_add_rx_filter_ext(dev, callback, user_data, filter);
if (filter_id >= 0) { if (filter_id >= 0) {
filter_id += NUM_STD_FILTER_DATA; filter_id += cbs->num_std;
} }
} else { } else {
filter_id = can_mcan_add_rx_filter_std(dev, callback, user_data, filter); 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) 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; struct can_mcan_data *data = dev->data;
int err; int err;
k_mutex_lock(&data->lock, K_FOREVER); k_mutex_lock(&data->lock, K_FOREVER);
if (filter_id >= NUM_STD_FILTER_DATA) { if (filter_id >= cbs->num_std) {
filter_id -= NUM_STD_FILTER_DATA; filter_id -= cbs->num_std;
if (filter_id >= NUM_EXT_FILTER_DATA) { if (filter_id >= cbs->num_ext) {
LOG_ERR("Wrong filter id"); LOG_ERR("Wrong filter id");
k_mutex_unlock(&data->lock); k_mutex_unlock(&data->lock);
return; 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), filter_id * sizeof(struct can_mcan_ext_filter),
sizeof(struct can_mcan_ext_filter)); sizeof(struct can_mcan_ext_filter));
if (err != 0) { if (err != 0) {
LOG_ERR("failed to clear ext filter element (err %d)", err); LOG_ERR("failed to clear ext filter element (err %d)", err);
} }
} else { } 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), filter_id * sizeof(struct can_mcan_std_filter),
sizeof(struct can_mcan_std_filter)); sizeof(struct can_mcan_std_filter));
if (err != 0) { if (err != 0) {
@ -1229,6 +1219,8 @@ unlock:
int can_mcan_configure_mram(const struct device *dev, uintptr_t mrba, uintptr_t mram) 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; uint32_t reg;
int err; 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); can_mcan_enable_configuration_change(dev);
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_STD_FILTER) & CAN_MCAN_SIDFC_FLSSA) | addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_STD_FILTER];
FIELD_PREP(CAN_MCAN_SIDFC_LSS, NUM_STD_FILTER_ELEMENTS); 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); err = can_mcan_write_reg(dev, CAN_MCAN_SIDFC, reg);
if (err != 0) { if (err != 0) {
return err; return err;
} }
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_EXT_FILTER) & CAN_MCAN_XIDFC_FLESA) | addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_EXT_FILTER];
FIELD_PREP(CAN_MCAN_XIDFC_LSS, NUM_EXT_FILTER_ELEMENTS); 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); err = can_mcan_write_reg(dev, CAN_MCAN_XIDFC, reg);
if (err != 0) { if (err != 0) {
return err; return err;
} }
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_RX_FIFO0) & CAN_MCAN_RXF0C_F0SA) | addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_RX_FIFO0];
FIELD_PREP(CAN_MCAN_RXF0C_F0S, NUM_RX_FIFO0_ELEMENTS); 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); err = can_mcan_write_reg(dev, CAN_MCAN_RXF0C, reg);
if (err != 0) { if (err != 0) {
return err; return err;
} }
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_RX_FIFO1) & CAN_MCAN_RXF1C_F1SA) | addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_RX_FIFO1];
FIELD_PREP(CAN_MCAN_RXF1C_F1S, NUM_RX_FIFO1_ELEMENTS); 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); err = can_mcan_write_reg(dev, CAN_MCAN_RXF1C, reg);
if (err != 0) { if (err != 0) {
return err; 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); err = can_mcan_write_reg(dev, CAN_MCAN_RXBC, reg);
if (err != 0) { if (err != 0) {
return err; return err;
} }
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_TX_EVENT_FIFO) & CAN_MCAN_TXEFC_EFSA) | addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_TX_EVENT_FIFO];
FIELD_PREP(CAN_MCAN_TXEFC_EFS, NUM_TX_EVENT_FIFO_ELEMENTS); 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); err = can_mcan_write_reg(dev, CAN_MCAN_TXEFC, reg);
if (err != 0) { if (err != 0) {
return err; return err;
} }
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_TX_BUFFER) & CAN_MCAN_TXBC_TBSA) | addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_TX_BUFFER];
FIELD_PREP(CAN_MCAN_TXBC_TFQS, NUM_TX_BUF_ELEMENTS) | CAN_MCAN_TXBC_TFQM; 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); err = can_mcan_write_reg(dev, CAN_MCAN_TXBC, reg);
if (err != 0) { if (err != 0) {
return err; 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) int can_mcan_init(const struct device *dev)
{ {
const struct can_mcan_config *config = dev->config; 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_data *data = dev->data;
struct can_timing timing; struct can_timing timing;
#ifdef CONFIG_CAN_FD_MODE #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->read_mram != NULL);
__ASSERT_NO_MSG(config->ops->write_mram != NULL); __ASSERT_NO_MSG(config->ops->write_mram != NULL);
__ASSERT_NO_MSG(config->ops->clear_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->lock);
k_mutex_init(&data->tx_mtx); 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 (config->phy != NULL) {
if (!device_is_ready(config->phy)) { if (!device_is_ready(config->phy)) {
@ -1503,5 +1508,5 @@ int can_mcan_init(const struct device *dev)
return err; 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 0x0F8
#define CAN_MCAN_TXEFA_EFAI GENMASK(4, 0) #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 * @name Indexes for the cells in the devicetree bosch,mram-cfg property
* description of the cells in the bosch,m_can-base devicetree binding. * @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 { /** offset cell index */
CAN_MCAN_MRAM_CFG_OFFSET = 0, #define CAN_MCAN_MRAM_CFG_OFFSET 0
CAN_MCAN_MRAM_CFG_STD_FILTER, /** std-filter-elements cell index */
CAN_MCAN_MRAM_CFG_EXT_FILTER, #define CAN_MCAN_MRAM_CFG_STD_FILTER 1
CAN_MCAN_MRAM_CFG_RX_FIFO0, /** ext-filter-elements cell index */
CAN_MCAN_MRAM_CFG_RX_FIFO1, #define CAN_MCAN_MRAM_CFG_EXT_FILTER 2
CAN_MCAN_MRAM_CFG_RX_BUFFER, /** rx-fifo0-elements cell index */
CAN_MCAN_MRAM_CFG_TX_EVENT, #define CAN_MCAN_MRAM_CFG_RX_FIFO0 3
CAN_MCAN_MRAM_CFG_TX_BUFFER, /** rx-fifo1-elements cell index */
CAN_MCAN_MRAM_CFG_NUM_CELLS #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 * @brief Get the Bosch M_CAN Message RAM offset
@ -413,7 +420,7 @@ enum can_mcan_mram_cfg {
* @return the Message RAM offset in bytes * @return the Message RAM offset in bytes
*/ */
#define CAN_MCAN_DT_MRAM_OFFSET(node_id) \ #define CAN_MCAN_DT_MRAM_OFFSET(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 0) 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 * @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 * @param node_id node identifier
* @return the number of standard (11-bit) filter elements * @return the number of standard (11-bit) filter elements
*/ */
#define CAN_MCAN_DT_MRAM_STD_FILTER_ELEM(node_id) \ #define CAN_MCAN_DT_MRAM_STD_FILTER_ELEMENTS(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 1) 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 * @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 * @param node_id node identifier
* @return the number of extended (29-bit) filter elements * @return the number of extended (29-bit) filter elements
*/ */
#define CAN_MCAN_DT_MRAM_EXT_FILTER_ELEM(node_id) \ #define CAN_MCAN_DT_MRAM_EXT_FILTER_ELEMENTS(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 2) 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 * @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 * @param node_id node identifier
* @return the number of Rx FIFO 0 elements * @return the number of Rx FIFO 0 elements
*/ */
#define CAN_MCAN_DT_MRAM_RX_FIFO0_ELEM(node_id) \ #define CAN_MCAN_DT_MRAM_RX_FIFO0_ELEMENTS(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 3) 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 * @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 * @param node_id node identifier
* @return the number of Rx FIFO 1 elements * @return the number of Rx FIFO 1 elements
*/ */
#define CAN_MCAN_DT_MRAM_RX_FIFO1_ELEM(node_id) \ #define CAN_MCAN_DT_MRAM_RX_FIFO1_ELEMENTS(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 4) 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 * @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 * @param node_id node identifier
* @return the number of Rx Buffer elements * @return the number of Rx Buffer elements
*/ */
#define CAN_MCAN_DT_MRAM_RX_BUFFER_ELEM(node_id) \ #define CAN_MCAN_DT_MRAM_RX_BUFFER_ELEMENTS(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 5) 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 * @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 * @param node_id node identifier
* @return the number of Tx Event FIFO elements * @return the number of Tx Event FIFO elements
*/ */
#define CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEM(node_id) \ #define CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEMENTS(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 6) 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 * @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 * @param node_id node identifier
* @return the number of Tx Buffer elements * @return the number of Tx Buffer elements
*/ */
#define CAN_MCAN_DT_MRAM_TX_BUFFER_ELEM(node_id) \ #define CAN_MCAN_DT_MRAM_TX_BUFFER_ELEMENTS(node_id) \
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 7) 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)) * @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 * @return the Message RAM offset in bytes
* @see CAN_MCAN_DT_MRAM_OFFSET() * @see CAN_MCAN_DT_MRAM_OFFSET()
*/ */
#define CAN_MCAN_DT_INST_MRAM_OFFSET(inst) \ #define CAN_MCAN_DT_INST_MRAM_OFFSET(inst) CAN_MCAN_DT_MRAM_OFFSET(DT_DRV_INST(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 * @param inst DT_DRV_COMPAT instance number
* @return the number of standard (11-bit) elements * @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) \ #define CAN_MCAN_DT_INST_MRAM_STD_FILTER_ELEMENTS(inst) \
CAN_MCAN_DT_MRAM_STD_FILTER_ELEMDT_DRV_INST(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 * @param inst DT_DRV_COMPAT instance number
* @return the number of extended (29-bit) elements * @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) \ #define CAN_MCAN_DT_INST_MRAM_EXT_FILTER_ELEMENTS(inst) \
CAN_MCAN_DT_MRAM_EXT_FILTER_ELEM(DT_DRV_INST(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 * @param inst DT_DRV_COMPAT instance number
* @return the number of Rx FIFO 0 elements * @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) \ #define CAN_MCAN_DT_INST_MRAM_RX_FIFO0_ELEMENTS(inst) \
CAN_MCAN_DT_MRAM_RX_FIFO0_ELEM(DT_DRV_INST(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 * @param inst DT_DRV_COMPAT instance number
* @return the number of Rx FIFO 1 elements * @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) \ #define CAN_MCAN_DT_INST_MRAM_RX_FIFO1_ELEMENTS(inst) \
CAN_MCAN_DT_MRAM_RX_FIFO1_ELEM(DT_DRV_INST(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 * @param inst DT_DRV_COMPAT instance number
* @return the number of Rx Buffer elements * @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) \ #define CAN_MCAN_DT_INST_MRAM_RX_BUFFER_ELEMENTS(inst) \
CAN_MCAN_DT_MRAM_RX_BUFFER_ELEM(DT_DRV_INST(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 * @param inst DT_DRV_COMPAT instance number
* @return the number of Tx Event FIFO elements * @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) \ #define CAN_MCAN_DT_INST_MRAM_TX_EVENT_FIFO_ELEMENTS(inst) \
CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEM(DT_DRV_INST(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 * @param inst DT_DRV_COMPAT instance number
* @return the number of Tx Buffer elements * @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) \ #define CAN_MCAN_DT_INST_MRAM_TX_BUFFER_ELEMENTS(inst) \
CAN_MCAN_DT_MRAM_TX_BUFFER_ELEM(DT_DRV_INST(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) * @brief Equivalent to CAN_MCAN_DT_MRAM_STD_FILTER_OFFSET(DT_DRV_INST(inst))
#define NUM_RX_FIFO0_ELEMENTS CAN_MCAN_DT_MRAM_RX_FIFO0_ELEM(MCAN_DT_PATH) * @param inst DT_DRV_COMPAT instance number
#define NUM_RX_FIFO1_ELEMENTS CAN_MCAN_DT_MRAM_RX_FIFO1_ELEM(MCAN_DT_PATH) * @return the base offset of standard (11-bit) filter elements in bytes
#define NUM_RX_BUF_ELEMENTS CAN_MCAN_DT_MRAM_RX_BUFFER_ELEM(MCAN_DT_PATH) * @see CAN_MCAN_DT_MRAM_STD_FILTER_OFFSET()
#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) #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"); * @brief Equivalent to CAN_MCAN_DT_MRAM_EXT_FILTER_OFFSET(DT_DRV_INST(inst))
BUILD_ASSERT(NUM_EXT_FILTER_ELEMENTS <= 64, "Maximum Extended filter elements exceeded"); * @param inst DT_DRV_COMPAT instance number
BUILD_ASSERT(NUM_RX_FIFO0_ELEMENTS <= 64, "Maximum Rx FIFO 0 elements exceeded"); * @return the base offset of extended (29-bit) filter elements in bytes
BUILD_ASSERT(NUM_RX_FIFO1_ELEMENTS <= 64, "Maximum Rx FIFO 1 elements exceeded"); * @see CAN_MCAN_DT_MRAM_EXT_FILTER_OFFSET()
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"); #define CAN_MCAN_DT_INST_MRAM_EXT_FILTER_OFFSET(inst) \
BUILD_ASSERT(NUM_TX_BUF_ELEMENTS <= 32, "Maximum Tx Buffer elements exceeded"); 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 * @brief Equivalent to CAN_MCAN_DT_MRAM_RX_FIFO0_OFFSET(DT_DRV_INST(inst))
#define NUM_EXT_FILTER_DATA CONFIG_CAN_MAX_EXT_ID_FILTER * @param inst DT_DRV_COMPAT instance number
#else * @return the base offset of Rx FIFO 0 elements in bytes
#define NUM_STD_FILTER_DATA NUM_STD_FILTER_ELEMENTS * @see CAN_MCAN_DT_MRAM_RX_FIFO0_OFFSET()
#define NUM_EXT_FILTER_DATA NUM_EXT_FILTER_ELEMENTS */
#endif #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 { struct can_mcan_rx_fifo_hdr {
union { union {
@ -689,42 +936,12 @@ struct can_mcan_ext_filter {
uint32_t eft: 2; /* Filter type */ uint32_t eft: 2; /* Filter type */
} __packed __aligned(4); } __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 can_mcan_data {
struct k_mutex lock; struct k_mutex lock;
struct k_sem tx_sem; struct k_sem tx_sem;
struct k_mutex tx_mtx; 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; can_state_change_callback_t state_change_cb;
void *state_change_cb_data; 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; bool started;
#ifdef CONFIG_CAN_FD_MODE #ifdef CONFIG_CAN_FD_MODE
bool fd; bool fd;
@ -814,8 +1031,90 @@ struct can_mcan_ops {
can_mcan_clear_mram_t clear_mram; 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_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; uint32_t bus_speed;
uint16_t sjw; uint16_t sjw;
uint16_t sample_point; uint16_t sample_point;
@ -834,17 +1133,62 @@ struct can_mcan_config {
const void *custom; 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 * @brief Static initializer for @p can_mcan_config struct
* *
* @param node_id Devicetree node identifier * @param node_id Devicetree node identifier
* @param _custom Pointer to custom driver frontend configuration structure * @param _custom Pointer to custom driver frontend configuration structure
* @param _ops Pointer to front-end @a can_mcan_ops * @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 #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, \ .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), \ .bus_speed = DT_PROP(node_id, bus_speed), \
.sjw = DT_PROP(node_id, sjw), \ .sjw = DT_PROP(node_id, sjw), \
.sample_point = DT_PROP_OR(node_id, sample_point, 0), \ .sample_point = DT_PROP_OR(node_id, sample_point, 0), \
@ -862,9 +1206,13 @@ struct can_mcan_config {
.custom = _custom, \ .custom = _custom, \
} }
#else /* CONFIG_CAN_FD_MODE */ #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, \ .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), \ .bus_speed = DT_PROP(node_id, bus_speed), \
.sjw = DT_PROP(node_id, sjw), \ .sjw = DT_PROP(node_id, sjw), \
.sample_point = DT_PROP_OR(node_id, sample_point, 0), \ .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 inst DT_DRV_COMPAT instance number
* @param _custom Pointer to custom driver frontend configuration structure * @param _custom Pointer to custom driver frontend configuration structure
* @param _ops Pointer to front-end @a can_mcan_ops * @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() * @see CAN_MCAN_DT_CONFIG_GET()
*/ */
#define CAN_MCAN_DT_CONFIG_INST_GET(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) CAN_MCAN_DT_CONFIG_GET(DT_DRV_INST(inst), _custom, _ops, _cbs)
/** /**
* @brief Initializer for a @a can_mcan_data struct * @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 * @param _custom Pointer to custom driver frontend data structure
*/ */
#define CAN_MCAN_DATA_INITIALIZER(_custom) \ #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 { struct mcux_mcan_config {
mm_reg_t base; mm_reg_t base;
mem_addr_t mram;
const struct device *clock_dev; const struct device *clock_dev;
clock_control_subsys_t clock_subsys; clock_control_subsys_t clock_subsys;
void (*irq_config_func)(const struct device *dev); void (*irq_config_func)(const struct device *dev);
const struct pinctrl_dev_config *pincfg; 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) 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; 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) 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; const struct can_mcan_config *mcan_config = dev->config;
struct mcux_mcan_data *mcux_data = mcan_data->custom; 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, static int mcux_mcan_write_mram(const struct device *dev, uint16_t offset, const void *src,
size_t len) size_t len)
{ {
struct can_mcan_data *mcan_data = dev->data; const struct can_mcan_config *mcan_config = dev->config;
struct mcux_mcan_data *mcux_data = mcan_data->custom; 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) static int mcux_mcan_clear_mram(const struct device *dev, uint16_t offset, size_t len)
{ {
struct can_mcan_data *mcan_data = dev->data; const struct can_mcan_config *mcan_config = dev->config;
struct mcux_mcan_data *mcux_data = mcan_data->custom; 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) 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 can_mcan_config *mcan_config = dev->config;
const struct mcux_mcan_config *mcux_config = mcan_config->custom; const struct mcux_mcan_config *mcux_config = mcan_config->custom;
struct can_mcan_data *mcan_data = dev->data; const uintptr_t mrba = mcux_config->mram & MCUX_MCAN_MRBA_BA;
struct mcux_mcan_data *mcux_data = mcan_data->custom;
const uintptr_t mrba = POINTER_TO_UINT(&mcux_data->msg_ram) & MCUX_MCAN_MRBA_BA;
int err; int err;
if (!device_is_ready(mcux_config->clock_dev)) { if (!device_is_ready(mcux_config->clock_dev)) {
@ -113,7 +108,7 @@ static int mcux_mcan_init(const struct device *dev)
return -EIO; 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) { if (err != 0) {
return -EIO; return -EIO;
} }
@ -204,12 +199,17 @@ static const struct can_mcan_ops mcux_mcan_ops = {
}; };
#define MCUX_MCAN_INIT(n) \ #define MCUX_MCAN_INIT(n) \
CAN_MCAN_DT_INST_BUILD_ASSERT_MRAM_CFG(n); \
PINCTRL_DT_INST_DEFINE(n); \ PINCTRL_DT_INST_DEFINE(n); \
\ \
static void mcux_mcan_irq_config_##n(const struct device *dev); \ 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 = { \ 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_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
.clock_subsys = (clock_control_subsys_t) \ .clock_subsys = (clock_control_subsys_t) \
DT_INST_CLOCKS_CELL(n, name), \ 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 = \ static const struct can_mcan_config can_mcan_config_##n = \
CAN_MCAN_DT_CONFIG_INST_GET(n, &mcux_mcan_config_##n, \ CAN_MCAN_DT_CONFIG_INST_GET(n, &mcux_mcan_config_##n, \
&mcux_mcan_ops); \ &mcux_mcan_ops, \
\ &mcux_mcan_cbs_##n); \
static struct mcux_mcan_data mcux_mcan_data_##n; \
\ \
static struct can_mcan_data can_mcan_data_##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, \ DEVICE_DT_INST_DEFINE(n, &mcux_mcan_init, NULL, \
&can_mcan_data_##n, \ &can_mcan_data_##n, \

View file

@ -21,16 +21,13 @@ LOG_MODULE_REGISTER(can_sam, CONFIG_CAN_LOG_LEVEL);
struct can_sam_config { struct can_sam_config {
mm_reg_t base; mm_reg_t base;
mem_addr_t mram;
void (*config_irq)(void); void (*config_irq)(void);
const struct atmel_sam_pmc_config clock_cfg; const struct atmel_sam_pmc_config clock_cfg;
const struct pinctrl_dev_config *pcfg; const struct pinctrl_dev_config *pcfg;
int divider; 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) 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; 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) 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; const struct can_mcan_config *mcan_config = dev->config;
struct can_sam_data *sam_data = mcan_data->custom; 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, static int can_sam_write_mram(const struct device *dev, uint16_t offset, const void *src,
size_t len) size_t len)
{ {
struct can_mcan_data *mcan_data = dev->data; const struct can_mcan_config *mcan_config = dev->config;
struct can_sam_data *sam_data = mcan_data->custom; 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) static int can_sam_clear_mram(const struct device *dev, uint16_t offset, size_t len)
{ {
struct can_mcan_data *mcan_data = dev->data; const struct can_mcan_config *mcan_config = dev->config;
struct can_sam_data *sam_data = mcan_data->custom; 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) 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_mcan_config *mcan_cfg = dev->config;
const struct can_sam_config *sam_cfg = mcan_cfg->custom; 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; int ret;
can_sam_clock_enable(sam_cfg); can_sam_clock_enable(sam_cfg);
@ -107,7 +102,7 @@ static int can_sam_init(const struct device *dev)
return ret; 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) { if (ret != 0) {
return ret; return ret;
} }
@ -195,8 +190,12 @@ static void config_can_##inst##_irq(void)
} }
#define CAN_SAM_CFG_INST(inst) \ #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 = { \ 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), \ .clock_cfg = SAM_DT_INST_CLOCK_PMC_CFG(inst), \
.divider = DT_INST_PROP(inst, divider), \ .divider = DT_INST_PROP(inst, divider), \
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ .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 = \ static const struct can_mcan_config can_mcan_cfg_##inst = \
CAN_MCAN_DT_CONFIG_INST_GET(inst, &can_sam_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) \ #define CAN_SAM_DATA_INST(inst) \
static struct can_sam_data can_sam_data_##inst; \
\
static struct can_mcan_data can_mcan_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) \ #define CAN_SAM_DEVICE_INST(inst) \
DEVICE_DT_INST_DEFINE(inst, &can_sam_init, NULL, \ DEVICE_DT_INST_DEFINE(inst, &can_sam_init, NULL, \
@ -221,6 +219,7 @@ static void config_can_##inst##_irq(void)
&can_sam_driver_api); &can_sam_driver_api);
#define CAN_SAM_INST(inst) \ #define CAN_SAM_INST(inst) \
CAN_MCAN_DT_INST_BUILD_ASSERT_MRAM_CFG(inst); \
PINCTRL_DT_INST_DEFINE(inst); \ PINCTRL_DT_INST_DEFINE(inst); \
CAN_SAM_IRQ_CFG_FUNCTION(inst) \ CAN_SAM_IRQ_CFG_FUNCTION(inst) \
CAN_SAM_CFG_INST(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 { struct can_sam0_config {
mm_reg_t base; mm_reg_t base;
mem_addr_t mram;
void (*config_irq)(void); void (*config_irq)(void);
const struct pinctrl_dev_config *pcfg; const struct pinctrl_dev_config *pcfg;
volatile uint32_t *mclk; volatile uint32_t *mclk;
@ -29,10 +30,6 @@ struct can_sam0_config {
int divider; 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) 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; 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) 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; const struct can_mcan_config *mcan_config = dev->config;
struct can_sam0_data *sam_data = mcan_data->custom; 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, static int can_sam0_write_mram(const struct device *dev, uint16_t offset, const void *src,
size_t len) size_t len)
{ {
struct can_mcan_data *mcan_data = dev->data; const struct can_mcan_config *mcan_config = dev->config;
struct can_sam0_data *sam_data = mcan_data->custom; 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) static int can_sam0_clear_mram(const struct device *dev, uint16_t offset, size_t len)
{ {
struct can_mcan_data *mcan_data = dev->data; const struct can_mcan_config *mcan_config = dev->config;
struct can_sam0_data *sam_data = mcan_data->custom; 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) 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_mcan_config *mcan_cfg = dev->config;
const struct can_sam0_config *sam_cfg = mcan_cfg->custom; 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; int ret;
can_sam0_clock_enable(sam_cfg); can_sam0_clock_enable(sam_cfg);
@ -135,7 +130,7 @@ static int can_sam0_init(const struct device *dev)
return ret; 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) { if (ret != 0) {
LOG_ERR("failed to configure message ram"); LOG_ERR("failed to configure message ram");
return ret; return ret;
@ -221,8 +216,12 @@ static void config_can_##inst##_irq(void) \
} }
#define CAN_SAM0_CFG_INST(inst) \ #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 = { \ 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 = (volatile uint32_t *)MCLK_MASK_DT_INT_REG_ADDR(inst), \
.mclk_mask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(inst, mclk, bit)), \ .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), \ .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 = \ 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) \ #define CAN_SAM0_DATA_INST(inst) \
static struct can_sam0_data can_sam0_data_##inst; \
\
static struct can_mcan_data can_mcan_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) \ #define CAN_SAM0_DEVICE_INST(inst) \
DEVICE_DT_INST_DEFINE(inst, &can_sam0_init, NULL, \ DEVICE_DT_INST_DEFINE(inst, &can_sam0_init, NULL, \
@ -248,6 +246,7 @@ static void config_can_##inst##_irq(void) \
&can_sam0_driver_api); &can_sam0_driver_api);
#define CAN_SAM0_INST(inst) \ #define CAN_SAM0_INST(inst) \
CAN_MCAN_DT_INST_BUILD_ASSERT_MRAM_CFG(inst); \
PINCTRL_DT_INST_DEFINE(inst); \ PINCTRL_DT_INST_DEFINE(inst); \
CAN_SAM0_IRQ_CFG_FUNCTION(inst) \ CAN_SAM0_IRQ_CFG_FUNCTION(inst) \
CAN_SAM0_CFG_INST(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, .clear_mram = can_stm32fd_clear_mram,
}; };
/* Assert that the Message RAM configuration matches the fixed hardware configuration */ #define CAN_STM32FD_BUILD_ASSERT_MRAM_CFG(inst) \
BUILD_ASSERT(NUM_STD_FILTER_ELEMENTS == 28, "Standard filter elements must be 28"); BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_STD_FILTER_ELEMENTS(inst) == 28, \
BUILD_ASSERT(NUM_EXT_FILTER_ELEMENTS == 8, "Extended filter elements must be 8"); "Standard filter elements must be 28"); \
BUILD_ASSERT(NUM_RX_FIFO0_ELEMENTS == 3, "Rx FIFO 0 elements must be 3"); BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_EXT_FILTER_ELEMENTS(inst) == 8, \
BUILD_ASSERT(NUM_RX_FIFO1_ELEMENTS == 3, "Rx FIFO 1 elements must be 3"); "Extended filter elements must be 8"); \
BUILD_ASSERT(NUM_RX_BUF_ELEMENTS == 0, "Rx Buffer elements must be 0"); BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_RX_FIFO0_ELEMENTS(inst) == 3, \
BUILD_ASSERT(NUM_TX_EVENT_FIFO_ELEMENTS == 3, "Tx Event FIFO elements must be 3"); "Rx FIFO 0 elements must be 3"); \
BUILD_ASSERT(NUM_TX_BUF_ELEMENTS == 3, "Tx Buffer elements must be 0"); 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) \ #define CAN_STM32FD_IRQ_CFG_FUNCTION(inst) \
static void config_can_##inst##_irq(void) \ static void config_can_##inst##_irq(void) \
@ -659,13 +666,22 @@ static void config_can_##inst##_irq(void) \
} }
#define CAN_STM32FD_CFG_INST(inst) \ #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); \ 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[] = \ static const struct stm32_pclken can_stm32fd_pclken_##inst[] = \
STM32_DT_INST_CLOCKS(inst); \ STM32_DT_INST_CLOCKS(inst); \
\ \
static const struct can_stm32fd_config can_stm32fd_cfg_##inst = { \ static const struct can_stm32fd_config can_stm32fd_cfg_##inst = { \
.base = (mm_reg_t)DT_INST_REG_ADDR_BY_NAME(inst, m_can), \ .base = CAN_MCAN_DT_INST_MCAN_ADDR(inst), \
.mram = (mem_addr_t)DT_INST_REG_ADDR_BY_NAME(inst, message_ram), \ .mram = CAN_MCAN_DT_INST_MRAM_ADDR(inst), \
.pclken = can_stm32fd_pclken_##inst, \ .pclken = can_stm32fd_pclken_##inst, \
.pclk_len = DT_INST_NUM_CLOCKS(inst), \ .pclk_len = DT_INST_NUM_CLOCKS(inst), \
.config_irq = config_can_##inst##_irq, \ .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 = \ static const struct can_mcan_config can_mcan_cfg_##inst = \
CAN_MCAN_DT_CONFIG_INST_GET(inst, &can_stm32fd_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) \ #define CAN_STM32FD_DATA_INST(inst) \
static struct can_mcan_data can_mcan_data_##inst = \ static struct can_mcan_data can_mcan_data_##inst = \
@ -688,6 +705,7 @@ static void config_can_##inst##_irq(void) \
&can_stm32fd_driver_api); &can_stm32fd_driver_api);
#define CAN_STM32FD_INST(inst) \ #define CAN_STM32FD_INST(inst) \
CAN_STM32FD_BUILD_ASSERT_MRAM_CFG(inst) \
CAN_STM32FD_IRQ_CFG_FUNCTION(inst) \ CAN_STM32FD_IRQ_CFG_FUNCTION(inst) \
CAN_STM32FD_CFG_INST(inst) \ CAN_STM32FD_CFG_INST(inst) \
CAN_STM32FD_DATA_INST(inst) \ CAN_STM32FD_DATA_INST(inst) \

View file

@ -215,13 +215,19 @@ static const struct can_mcan_ops can_stm32h7_ops = {
}; };
#define CAN_STM32H7_MCAN_INIT(n) \ #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); \ static void stm32h7_mcan_irq_config_##n(void); \
\ \
PINCTRL_DT_INST_DEFINE(n); \ 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 = { \ static const struct can_stm32h7_config can_stm32h7_cfg_##n = { \
.base = (mm_reg_t)DT_INST_REG_ADDR_BY_NAME(n, m_can), \ .base = CAN_MCAN_DT_INST_MCAN_ADDR(n), \
.mram = (mem_addr_t)DT_INST_REG_ADDR_BY_NAME(n, message_ram), \ .mram = CAN_MCAN_DT_INST_MRAM_ADDR(n), \
.config_irq = stm32h7_mcan_irq_config_##n, \ .config_irq = stm32h7_mcan_irq_config_##n, \
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
.pclken = { \ .pclken = { \
@ -232,7 +238,8 @@ static const struct can_mcan_ops can_stm32h7_ops = {
\ \
static const struct can_mcan_config can_mcan_cfg_##n = \ static const struct can_mcan_config can_mcan_cfg_##n = \
CAN_MCAN_DT_CONFIG_INST_GET(n, &can_stm32h7_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 = \ static struct can_mcan_data can_mcan_data_##n = \
CAN_MCAN_DATA_INITIALIZER(NULL); \ CAN_MCAN_DATA_INITIALIZER(NULL); \

View file

@ -44,12 +44,6 @@
status = "disabled"; status = "disabled";
}; };
can {
compatible = "bosch,m_can-base";
#address-cells = <1>;
#size-cells = <1>;
bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>;
can0: can@42001c00 { can0: can@42001c00 {
compatible = "atmel,sam0-can"; compatible = "atmel,sam0-can";
reg = <0x42001c00 0x100>; reg = <0x42001c00 0x100>;
@ -57,6 +51,7 @@
interrupt-names = "LINE_0"; interrupt-names = "LINE_0";
clocks = <&gclk 26>, <&mclk 0x10 8>; clocks = <&gclk 26>, <&mclk 0x10 8>;
clock-names = "GCLK", "MCLK"; clock-names = "GCLK", "MCLK";
bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>;
divider = <12>; divider = <12>;
sjw = <1>; sjw = <1>;
sample-point = <875>; sample-point = <875>;
@ -72,6 +67,7 @@
interrupt-names = "LINE_0"; interrupt-names = "LINE_0";
clocks = <&gclk 27>, <&mclk 0x10 9>; clocks = <&gclk 27>, <&mclk 0x10 9>;
clock-names = "GCLK", "MCLK"; clock-names = "GCLK", "MCLK";
bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>;
divider = <12>; divider = <12>;
sjw = <1>; sjw = <1>;
sample-point = <875>; sample-point = <875>;
@ -81,4 +77,3 @@
}; };
}; };
}; };
};

View file

@ -408,12 +408,6 @@
status = "disabled"; status = "disabled";
}; };
can {
compatible = "bosch,m_can-base";
#address-cells = <1>;
#size-cells = <1>;
bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>;
can0: can@40030000 { can0: can@40030000 {
compatible = "atmel,sam-can"; compatible = "atmel,sam-can";
reg = <0x40030000 0x100>; reg = <0x40030000 0x100>;
@ -421,6 +415,7 @@
interrupt-names = "LINE_0", "LINE_1"; interrupt-names = "LINE_0", "LINE_1";
clocks = <&pmc PMC_TYPE_PERIPHERAL 35>; clocks = <&pmc PMC_TYPE_PERIPHERAL 35>;
divider = <6>; divider = <6>;
bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>;
sjw = <1>; sjw = <1>;
sample-point = <875>; sample-point = <875>;
sjw-data = <1>; sjw-data = <1>;
@ -435,13 +430,13 @@
interrupt-names = "LINE_0", "LINE_1"; interrupt-names = "LINE_0", "LINE_1";
clocks = <&pmc PMC_TYPE_PERIPHERAL 37>; clocks = <&pmc PMC_TYPE_PERIPHERAL 37>;
divider = <6>; divider = <6>;
bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>;
sjw = <1>; sjw = <1>;
sample-point = <875>; sample-point = <875>;
sjw-data = <1>; sjw-data = <1>;
sample-point-data = <875>; sample-point-data = <875>;
status = "disabled"; status = "disabled";
}; };
};
rstc: rstc@400e1800 { rstc: rstc@400e1800 {
compatible = "atmel,sam-rstc"; compatible = "atmel,sam-rstc";

View file

@ -30,25 +30,19 @@
}; };
}; };
can {
compatible = "bosch,m_can-base";
#address-cells = <1>;
#size-cells = <1>;
bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>;
can1: can@40006400 { can1: can@40006400 {
compatible = "st,stm32-fdcan"; compatible = "st,stm32-fdcan";
reg = <0x40006400 0x400>, <0x4000B400 0x350>; reg = <0x40006400 0x400>, <0x4000b400 0x350>;
reg-names = "m_can", "message_ram"; reg-names = "m_can", "message_ram";
interrupts = <21 0>, <22 0>; interrupts = <21 0>, <22 0>;
interrupt-names = "LINE_0", "LINE_1"; interrupt-names = "LINE_0", "LINE_1";
clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00001000>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00001000>;
status = "disabled"; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>;
sjw = <1>; sjw = <1>;
sample-point = <875>; sample-point = <875>;
sjw-data = <1>; sjw-data = <1>;
sample-point-data = <875>; sample-point-data = <875>;
}; status = "disabled";
}; };
usart5: serial@40005000 { usart5: serial@40005000 {

View file

@ -381,25 +381,19 @@
status = "disabled"; status = "disabled";
}; };
can {
compatible = "bosch,m_can-base";
#address-cells = <1>;
#size-cells = <1>;
bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>;
can1: can@40006400 { can1: can@40006400 {
compatible = "st,stm32-fdcan"; compatible = "st,stm32-fdcan";
reg = <0x40006400 0x400>, <0x4000A400 0x350>; reg = <0x40006400 0x400>, <0x4000a400 0x350>;
reg-names = "m_can", "message_ram"; reg-names = "m_can", "message_ram";
interrupts = <21 0>, <22 0>; interrupts = <21 0>, <22 0>;
interrupt-names = "LINE_0", "LINE_1"; interrupt-names = "LINE_0", "LINE_1";
clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>;
status = "disabled"; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>;
sjw = <1>; sjw = <1>;
sample-point = <875>; sample-point = <875>;
sjw-data = <1>; sjw-data = <1>;
sample-point-data = <875>; sample-point-data = <875>;
}; status = "disabled";
}; };
lptim1: timers@40007c00 { lptim1: timers@40007c00 {

View file

@ -84,20 +84,19 @@
status = "disabled"; status = "disabled";
}; };
can { can3: can@40006c00 {
can3: can@40006C00 {
compatible = "st,stm32-fdcan"; compatible = "st,stm32-fdcan";
reg = <0x40006C00 0x400>, <0x4000AAA0 0x350>; reg = <0x40006c00 0x400>, <0x4000a400 0x9f0>;
reg-names = "m_can", "message_ram"; reg-names = "m_can", "message_ram";
interrupts = <88 0>, <89 0>; interrupts = <88 0>, <89 0>;
interrupt-names = "LINE_0", "LINE_1"; interrupt-names = "LINE_0", "LINE_1";
clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>;
status = "disabled"; bosch,mram-cfg = <0x6a0 28 8 3 3 0 3 3>;
sjw = <1>; sjw = <1>;
sample-point = <875>; sample-point = <875>;
sjw-data = <1>; sjw-data = <1>;
sample-point-data = <875>; sample-point-data = <875>;
}; status = "disabled";
}; };
}; };
}; };

View file

@ -10,20 +10,19 @@
soc { soc {
compatible = "st,stm32g491", "st,stm32g4", "simple-bus"; compatible = "st,stm32g491", "st,stm32g4", "simple-bus";
can {
can2: can@40006800 { can2: can@40006800 {
compatible = "st,stm32-fdcan"; compatible = "st,stm32-fdcan";
reg = <0x40006800 0x400>, <0x4000A750 0x350>; reg = <0x40006800 0x400>, <0x4000a400 0x6a0>;
reg-names = "m_can", "message_ram"; reg-names = "m_can", "message_ram";
interrupts = <86 0>, <87 0>; interrupts = <86 0>, <87 0>;
interrupt-names = "LINE_0", "LINE_1"; interrupt-names = "LINE_0", "LINE_1";
clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>;
status = "disabled";
sjw = <1>; sjw = <1>;
bosch,mram-cfg = <0x350 28 8 3 3 0 3 3>;
sample-point = <875>; sample-point = <875>;
sjw-data = <1>; sjw-data = <1>;
sample-point-data = <875>; sample-point-data = <875>;
}; status = "disabled";
}; };
timers20: timers@40015000 { timers20: timers@40015000 {

View file

@ -436,12 +436,6 @@
status = "disabled"; status = "disabled";
}; };
can {
compatible = "bosch,m_can-base";
#address-cells = <1>;
#size-cells = <1>;
bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>;
can1: can@4000a400 { can1: can@4000a400 {
compatible = "st,stm32-fdcan"; compatible = "st,stm32-fdcan";
reg = <0x4000a400 0x400>, <0x4000ac00 0x350>; reg = <0x4000a400 0x400>, <0x4000ac00 0x350>;
@ -449,12 +443,12 @@
interrupts = <39 0>, <40 0>; interrupts = <39 0>, <40 0>;
interrupt-names = "LINE_0", "LINE_1"; interrupt-names = "LINE_0", "LINE_1";
clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>;
status = "disabled"; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>;
sjw = <1>; sjw = <1>;
sample-point = <875>; sample-point = <875>;
sjw-data = <1>; sjw-data = <1>;
sample-point-data = <875>; sample-point-data = <875>;
}; status = "disabled";
}; };
rng: rng@420c0800 { rng: rng@420c0800 {

View file

@ -293,21 +293,20 @@
status = "disabled"; status = "disabled";
}; };
can {
can2: can@4000a800 { can2: can@4000a800 {
compatible = "st,stm32-fdcan"; compatible = "st,stm32-fdcan";
reg = <0x4000a800 0x400>, <0x4000af50 0x350>; reg = <0x4000a800 0x400>, <0x4000ac00 0x6a0>;
reg-names = "m_can", "message_ram"; reg-names = "m_can", "message_ram";
interrupts = <109 0>, <110 0>; interrupts = <109 0>, <110 0>;
interrupt-names = "LINE_0", "LINE_1"; interrupt-names = "LINE_0", "LINE_1";
/* common clock FDCAN 1 & 2 */ /* common clock FDCAN 1 & 2 */
clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>;
status = "disabled"; bosch,mram-cfg = <0x350 28 8 3 3 0 3 3>;
sjw = <1>; sjw = <1>;
sample-point = <875>; sample-point = <875>;
sjw-data = <1>; sjw-data = <1>;
sample-point-data = <875>; sample-point-data = <875>;
}; status = "disabled";
}; };
}; };
}; };

View file

@ -465,12 +465,6 @@
status = "disabled"; status = "disabled";
}; };
can {
compatible = "bosch,m_can-base";
#address-cells = <1>;
#size-cells = <1>;
bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>;
can1: can@4000a000 { can1: can@4000a000 {
compatible = "st,stm32h7-fdcan"; compatible = "st,stm32h7-fdcan";
reg = <0x4000a000 0x400>, <0x4000ac00 0x350>; reg = <0x4000a000 0x400>, <0x4000ac00 0x350>;
@ -478,26 +472,27 @@
clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>;
interrupts = <19 0>, <21 0>, <63 0>; interrupts = <19 0>, <21 0>, <63 0>;
interrupt-names = "LINE_0", "LINE_1", "CALIB"; interrupt-names = "LINE_0", "LINE_1", "CALIB";
status = "disabled"; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>;
sjw = <1>; sjw = <1>;
sample-point = <875>; sample-point = <875>;
sjw-data = <1>; sjw-data = <1>;
sample-point-data = <875>; sample-point-data = <875>;
status = "disabled";
}; };
can2: can@4000a400 { can2: can@4000a400 {
compatible = "st,stm32h7-fdcan"; compatible = "st,stm32h7-fdcan";
reg = <0x4000a400 0x400>, <0x4000ac00 0x350>; reg = <0x4000a400 0x400>, <0x4000ac00 0x6a0>;
reg-names = "m_can", "message_ram"; reg-names = "m_can", "message_ram";
clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>;
interrupts = <20 0>, <22 0>, <63 0>; interrupts = <20 0>, <22 0>, <63 0>;
interrupt-names = "LINE_0", "LINE_1", "CALIB"; interrupt-names = "LINE_0", "LINE_1", "CALIB";
status = "disabled"; bosch,mram-cfg = <0x350 28 8 3 3 0 3 3>;
sjw = <1>; sjw = <1>;
sample-point = <875>; sample-point = <875>;
sjw-data = <1>; sjw-data = <1>;
sample-point-data = <875>; sample-point-data = <875>;
}; status = "disabled";
}; };
timers1: timers@40010000 { timers1: timers@40010000 {

View file

@ -117,21 +117,20 @@
status = "disabled"; status = "disabled";
}; };
can { can3: can@4000d400 {
can3: can@4000D400 {
compatible = "st,stm32h7-fdcan"; compatible = "st,stm32h7-fdcan";
reg = <0x4000D400 0x400>, <0x4000ac00 0x350>; reg = <0x4000d400 0x400>, <0x4000ac00 0x9f0>;
reg-names = "m_can", "message_ram"; reg-names = "m_can", "message_ram";
clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>;
interrupts = <159 0>, <160 0>, <63 0>; interrupts = <159 0>, <160 0>, <63 0>;
interrupt-names = "LINE_0", "LINE_1", "CALIB"; interrupt-names = "LINE_0", "LINE_1", "CALIB";
bosch,mram-cfg = <0x6a0 28 8 3 3 0 3 3>;
sjw = <1>; sjw = <1>;
sample-point = <875>; sample-point = <875>;
sjw-data = <1>; sjw-data = <1>;
sample-point-data = <875>; sample-point-data = <875>;
status = "disabled"; status = "disabled";
}; };
};
rtc@58004000 { rtc@58004000 {
bbram: backup_regs { bbram: backup_regs {

View file

@ -770,12 +770,6 @@
num-sampling-time-common-channels = <2>; num-sampling-time-common-channels = <2>;
}; };
can {
compatible = "bosch,m_can-base";
#address-cells = <1>;
#size-cells = <1>;
bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>;
can1: can@4000a400 { can1: can@4000a400 {
compatible = "st,stm32-fdcan"; compatible = "st,stm32-fdcan";
reg = <0x4000a400 0x400>, <0x4000ac00 0x350>; reg = <0x4000a400 0x400>, <0x4000ac00 0x350>;
@ -783,12 +777,12 @@
interrupts = <39 0>, <40 0>; interrupts = <39 0>, <40 0>;
interrupt-names = "LINE_0", "LINE_1"; interrupt-names = "LINE_0", "LINE_1";
clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>;
status = "disabled"; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>;
sjw = <1>; sjw = <1>;
sample-point = <875>; sample-point = <875>;
sjw-data = <1>; sjw-data = <1>;
sample-point-data = <875>; sample-point-data = <875>;
}; status = "disabled";
}; };
ucpd1: ucpd@4000dc00 { ucpd1: ucpd@4000dc00 {

View file

@ -3,7 +3,7 @@ description: Specialization of Bosch m_can CAN-FD controller for Atmel SAM
compatible: "atmel,sam-can" compatible: "atmel,sam-can"
include: include:
- name: can-fd-controller.yaml - name: bosch,m_can-base.yaml
- name: pinctrl-device.yaml - name: pinctrl-device.yaml
properties: properties:

View file

@ -3,7 +3,7 @@ description: Specialization of Bosch m_can CAN-FD controller for Atmel SAM0
compatible: "atmel,sam0-can" compatible: "atmel,sam0-can"
include: include:
- name: can-fd-controller.yaml - name: bosch,m_can-base.yaml
- name: pinctrl-device.yaml - name: pinctrl-device.yaml
properties: properties:

View file

@ -1,6 +1,6 @@
description: Bosch M_CAN CAN-FD controller base description: Bosch M_CAN CAN-FD controller base
compatible: "bosch,m_can-base" include: [can-fd-controller.yaml]
properties: properties:
bosch,mram-cfg: bosch,mram-cfg:

View file

@ -2,7 +2,7 @@ description: NXP LPC SoC series MCAN CAN-FD controller
compatible: "nxp,lpc-mcan" compatible: "nxp,lpc-mcan"
include: [can-fd-controller.yaml, "bosch,m_can-base.yaml", pinctrl-device.yaml] include: ["bosch,m_can-base.yaml", pinctrl-device.yaml]
properties: properties:
reg: reg:

View file

@ -2,7 +2,7 @@ description: ST STM32 FDCAN CAN-FD controller
compatible: "st,stm32-fdcan" compatible: "st,stm32-fdcan"
include: ["can-fd-controller.yaml", "pinctrl-device.yaml"] include: ["bosch,m_can-base.yaml", "pinctrl-device.yaml"]
properties: properties:
reg: reg:

View file

@ -2,7 +2,7 @@ description: ST STM32H7 series FDCAN CAN-FD controller
compatible: "st,stm32h7-fdcan" compatible: "st,stm32h7-fdcan"
include: ["can-fd-controller.yaml", "pinctrl-device.yaml"] include: ["bosch,m_can-base.yaml", "pinctrl-device.yaml"]
properties: properties:
clocks: clocks: