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:
parent
d112e08f0c
commit
0f36f1a3ee
24 changed files with 878 additions and 546 deletions
|
@ -342,6 +342,7 @@ int can_mcan_start(const struct device *dev)
|
|||
int can_mcan_stop(const struct device *dev)
|
||||
{
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
const struct can_mcan_callbacks *cbs = config->callbacks;
|
||||
struct can_mcan_data *data = dev->data;
|
||||
can_tx_callback_t tx_cb;
|
||||
uint32_t tx_idx;
|
||||
|
@ -370,12 +371,12 @@ int can_mcan_stop(const struct device *dev)
|
|||
|
||||
data->started = false;
|
||||
|
||||
for (tx_idx = 0U; tx_idx < ARRAY_SIZE(data->tx_fin_cb); tx_idx++) {
|
||||
tx_cb = data->tx_fin_cb[tx_idx];
|
||||
for (tx_idx = 0U; tx_idx < cbs->num_tx; tx_idx++) {
|
||||
tx_cb = cbs->tx[tx_idx].function;
|
||||
|
||||
if (tx_cb != NULL) {
|
||||
data->tx_fin_cb[tx_idx] = NULL;
|
||||
tx_cb(dev, -ENETDOWN, data->tx_fin_cb_arg[tx_idx]);
|
||||
cbs->tx[tx_idx].function = NULL;
|
||||
tx_cb(dev, -ENETDOWN, cbs->tx[tx_idx].user_data);
|
||||
k_sem_give(&data->tx_sem);
|
||||
}
|
||||
}
|
||||
|
@ -476,6 +477,8 @@ static void can_mcan_state_change_handler(const struct device *dev)
|
|||
|
||||
static void can_mcan_tc_event_handler(const struct device *dev)
|
||||
{
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
const struct can_mcan_callbacks *cbs = config->callbacks;
|
||||
struct can_mcan_data *data = dev->data;
|
||||
struct can_mcan_tx_event_fifo tx_event;
|
||||
can_tx_callback_t tx_cb;
|
||||
|
@ -491,7 +494,8 @@ static void can_mcan_tc_event_handler(const struct device *dev)
|
|||
|
||||
while ((txefs & CAN_MCAN_TXEFS_EFFL) != 0U) {
|
||||
event_idx = FIELD_GET(CAN_MCAN_TXEFS_EFGI, txefs);
|
||||
err = can_mcan_read_mram(dev, CAN_MCAN_MRAM_OFFSET_TX_EVENT_FIFO +
|
||||
err = can_mcan_read_mram(dev,
|
||||
config->mram_offsets[CAN_MCAN_MRAM_CFG_TX_EVENT_FIFO] +
|
||||
event_idx * sizeof(struct can_mcan_tx_event_fifo),
|
||||
&tx_event,
|
||||
sizeof(struct can_mcan_tx_event_fifo));
|
||||
|
@ -510,9 +514,10 @@ static void can_mcan_tc_event_handler(const struct device *dev)
|
|||
|
||||
k_sem_give(&data->tx_sem);
|
||||
|
||||
tx_cb = data->tx_fin_cb[tx_idx];
|
||||
data->tx_fin_cb[tx_idx] = NULL;
|
||||
tx_cb(dev, 0, data->tx_fin_cb_arg[tx_idx]);
|
||||
__ASSERT_NO_MSG(tx_idx <= cbs->num_tx);
|
||||
tx_cb = cbs->tx[tx_idx].function;
|
||||
cbs->tx[tx_idx].function = NULL;
|
||||
tx_cb(dev, 0, cbs->tx[tx_idx].user_data);
|
||||
|
||||
err = can_mcan_read_reg(dev, CAN_MCAN_TXEFS, &txefs);
|
||||
if (err != 0) {
|
||||
|
@ -573,16 +578,16 @@ void can_mcan_line_0_isr(const struct device *dev)
|
|||
static void can_mcan_get_message(const struct device *dev, uint16_t fifo_offset,
|
||||
uint16_t fifo_status_reg, uint16_t fifo_ack_reg)
|
||||
{
|
||||
struct can_mcan_data *data = dev->data;
|
||||
uint32_t get_idx, filt_idx;
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
const struct can_mcan_callbacks *cbs = config->callbacks;
|
||||
struct can_mcan_rx_fifo_hdr hdr;
|
||||
struct can_frame frame = {0};
|
||||
can_rx_callback_t cb;
|
||||
void *user_data;
|
||||
uint8_t flags;
|
||||
uint32_t get_idx;
|
||||
uint32_t filt_idx;
|
||||
int data_length;
|
||||
void *cb_arg;
|
||||
struct can_mcan_rx_fifo_hdr hdr;
|
||||
bool rtr_filter_mask;
|
||||
bool rtr_filter;
|
||||
bool fd_frame_filter;
|
||||
uint32_t fifo_status;
|
||||
int err;
|
||||
|
||||
|
@ -630,25 +635,25 @@ static void can_mcan_get_message(const struct device *dev, uint16_t fifo_offset,
|
|||
if (hdr.xtd != 0) {
|
||||
frame.id = hdr.ext_id;
|
||||
frame.flags |= CAN_FRAME_IDE;
|
||||
rtr_filter_mask = (data->ext_filt_rtr_mask & BIT(filt_idx)) != 0U;
|
||||
rtr_filter = (data->ext_filt_rtr & BIT(filt_idx)) != 0;
|
||||
fd_frame_filter = (data->ext_filt_fd_frame & BIT(filt_idx)) != 0U;
|
||||
flags = cbs->ext[filt_idx].flags;
|
||||
} else {
|
||||
frame.id = hdr.std_id;
|
||||
rtr_filter_mask = (data->std_filt_rtr_mask & BIT(filt_idx)) != 0U;
|
||||
rtr_filter = (data->std_filt_rtr & BIT(filt_idx)) != 0;
|
||||
fd_frame_filter = (data->std_filt_fd_frame & BIT(filt_idx)) != 0U;
|
||||
flags = cbs->std[filt_idx].flags;
|
||||
}
|
||||
|
||||
if (rtr_filter_mask && (rtr_filter != ((frame.flags & CAN_FRAME_RTR) != 0U))) {
|
||||
/* RTR bit does not match filter RTR mask, drop frame */
|
||||
if (((frame.flags & CAN_FRAME_RTR) == 0U && (flags & CAN_FILTER_DATA) == 0U) ||
|
||||
((frame.flags & CAN_FRAME_RTR) != 0U && (flags & CAN_FILTER_RTR) == 0U)) {
|
||||
/* RTR bit does not match filter, drop frame */
|
||||
err = can_mcan_write_reg(dev, fifo_ack_reg, get_idx);
|
||||
if (err != 0) {
|
||||
return;
|
||||
}
|
||||
goto ack;
|
||||
} else if (fd_frame_filter != ((frame.flags & CAN_FRAME_FDF) != 0U)) {
|
||||
/* FD bit does not match filter FD frame, drop frame */
|
||||
}
|
||||
|
||||
if (((frame.flags & CAN_FRAME_FDF) != 0U && (flags & CAN_FILTER_FDF) == 0U) ||
|
||||
((frame.flags & CAN_FRAME_FDF) == 0U && (flags & CAN_FILTER_FDF) != 0U)) {
|
||||
/* FDF bit does not match filter, drop frame */
|
||||
err = can_mcan_write_reg(dev, fifo_ack_reg, get_idx);
|
||||
if (err != 0) {
|
||||
return;
|
||||
|
@ -670,17 +675,19 @@ static void can_mcan_get_message(const struct device *dev, uint16_t fifo_offset,
|
|||
|
||||
if ((frame.flags & CAN_FRAME_IDE) != 0) {
|
||||
LOG_DBG("Frame on filter %d, ID: 0x%x",
|
||||
filt_idx + NUM_STD_FILTER_DATA, frame.id);
|
||||
cb = data->rx_cb_ext[filt_idx];
|
||||
cb_arg = data->cb_arg_ext[filt_idx];
|
||||
filt_idx + cbs->num_std, frame.id);
|
||||
__ASSERT_NO_MSG(filt_idx <= cbs->num_ext);
|
||||
cb = cbs->ext[filt_idx].function;
|
||||
user_data = cbs->ext[filt_idx].user_data;
|
||||
} else {
|
||||
LOG_DBG("Frame on filter %d, ID: 0x%x", filt_idx, frame.id);
|
||||
cb = data->rx_cb_std[filt_idx];
|
||||
cb_arg = data->cb_arg_std[filt_idx];
|
||||
__ASSERT_NO_MSG(filt_idx <= cbs->num_std);
|
||||
cb = cbs->std[filt_idx].function;
|
||||
user_data = cbs->std[filt_idx].user_data;
|
||||
}
|
||||
|
||||
if (cb) {
|
||||
cb(dev, &frame, cb_arg);
|
||||
cb(dev, &frame, user_data);
|
||||
} else {
|
||||
LOG_DBG("cb missing");
|
||||
}
|
||||
|
@ -703,6 +710,7 @@ ack:
|
|||
|
||||
void can_mcan_line_1_isr(const struct device *dev)
|
||||
{
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
const uint32_t events =
|
||||
CAN_MCAN_IR_RF0N | CAN_MCAN_IR_RF1N | CAN_MCAN_IR_RF0L | CAN_MCAN_IR_RF1L;
|
||||
uint32_t ir;
|
||||
|
@ -716,14 +724,14 @@ void can_mcan_line_1_isr(const struct device *dev)
|
|||
while ((ir & events) != 0U) {
|
||||
if ((ir & CAN_MCAN_IR_RF0N) != 0U) {
|
||||
LOG_DBG("RX FIFO0 INT");
|
||||
can_mcan_get_message(dev, CAN_MCAN_MRAM_OFFSET_RX_FIFO0, CAN_MCAN_RXF0S,
|
||||
CAN_MCAN_RXF0A);
|
||||
can_mcan_get_message(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_RX_FIFO0],
|
||||
CAN_MCAN_RXF0S, CAN_MCAN_RXF0A);
|
||||
}
|
||||
|
||||
if ((ir & CAN_MCAN_IR_RF1N) != 0U) {
|
||||
LOG_DBG("RX FIFO1 INT");
|
||||
can_mcan_get_message(dev, CAN_MCAN_MRAM_OFFSET_RX_FIFO1, CAN_MCAN_RXF1S,
|
||||
CAN_MCAN_RXF1A);
|
||||
can_mcan_get_message(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_RX_FIFO1],
|
||||
CAN_MCAN_RXF1S, CAN_MCAN_RXF1A);
|
||||
}
|
||||
|
||||
if ((ir & CAN_MCAN_IR_RF0L) != 0U) {
|
||||
|
@ -801,6 +809,8 @@ int can_mcan_recover(const struct device *dev, k_timeout_t timeout)
|
|||
int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_timeout_t timeout,
|
||||
can_tx_callback_t callback, void *user_data)
|
||||
{
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
const struct can_mcan_callbacks *cbs = config->callbacks;
|
||||
struct can_mcan_data *data = dev->data;
|
||||
size_t data_length = can_dlc_to_bytes(frame->dlc);
|
||||
struct can_mcan_tx_buffer_hdr tx_hdr = {
|
||||
|
@ -901,7 +911,7 @@ int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_tim
|
|||
tx_hdr.std_id = frame->id & CAN_STD_ID_MASK;
|
||||
}
|
||||
|
||||
err = can_mcan_write_mram(dev, CAN_MCAN_MRAM_OFFSET_TX_BUFFER + put_idx *
|
||||
err = can_mcan_write_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_TX_BUFFER] + put_idx *
|
||||
sizeof(struct can_mcan_tx_buffer) +
|
||||
offsetof(struct can_mcan_tx_buffer, hdr),
|
||||
&tx_hdr, sizeof(struct can_mcan_tx_buffer_hdr));
|
||||
|
@ -910,7 +920,7 @@ int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_tim
|
|||
return err;
|
||||
}
|
||||
|
||||
err = can_mcan_write_mram(dev, CAN_MCAN_MRAM_OFFSET_TX_BUFFER + put_idx *
|
||||
err = can_mcan_write_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_TX_BUFFER] + put_idx *
|
||||
sizeof(struct can_mcan_tx_buffer) +
|
||||
offsetof(struct can_mcan_tx_buffer, data_32),
|
||||
&frame->data_32, ROUND_UP(data_length, sizeof(uint32_t)));
|
||||
|
@ -919,8 +929,9 @@ int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_tim
|
|||
return err;
|
||||
}
|
||||
|
||||
data->tx_fin_cb[put_idx] = callback;
|
||||
data->tx_fin_cb_arg[put_idx] = user_data;
|
||||
__ASSERT_NO_MSG(put_idx <= cbs->num_tx);
|
||||
cbs->tx[put_idx].function = callback;
|
||||
cbs->tx[put_idx].user_data = user_data;
|
||||
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_TXBAR, BIT(put_idx));
|
||||
if (err != 0) {
|
||||
|
@ -935,12 +946,14 @@ unlock:
|
|||
|
||||
static int can_mcan_get_free_std(const struct device *dev)
|
||||
{
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
const struct can_mcan_callbacks *cbs = config->callbacks;
|
||||
struct can_mcan_std_filter filter;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_STD_FILTER_DATA; ++i) {
|
||||
err = can_mcan_read_mram(dev, CAN_MCAN_MRAM_OFFSET_STD_FILTER +
|
||||
for (i = 0; i < cbs->num_std; ++i) {
|
||||
err = can_mcan_read_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_STD_FILTER] +
|
||||
i * sizeof(struct can_mcan_std_filter), &filter,
|
||||
sizeof(struct can_mcan_std_filter));
|
||||
if (err != 0) {
|
||||
|
@ -958,12 +971,13 @@ static int can_mcan_get_free_std(const struct device *dev)
|
|||
|
||||
int can_mcan_get_max_filters(const struct device *dev, bool ide)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
const struct can_mcan_callbacks *cbs = config->callbacks;
|
||||
|
||||
if (ide) {
|
||||
return NUM_EXT_FILTER_DATA;
|
||||
return cbs->num_ext;
|
||||
} else {
|
||||
return NUM_STD_FILTER_DATA;
|
||||
return cbs->num_std;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -975,6 +989,8 @@ int can_mcan_get_max_filters(const struct device *dev, bool ide)
|
|||
int can_mcan_add_rx_filter_std(const struct device *dev, can_rx_callback_t callback,
|
||||
void *user_data, const struct can_filter *filter)
|
||||
{
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
const struct can_mcan_callbacks *cbs = config->callbacks;
|
||||
struct can_mcan_data *data = dev->data;
|
||||
struct can_mcan_std_filter filter_element = {
|
||||
.id1 = filter->id,
|
||||
|
@ -996,7 +1012,7 @@ int can_mcan_add_rx_filter_std(const struct device *dev, can_rx_callback_t callb
|
|||
/* TODO proper fifo balancing */
|
||||
filter_element.sfce = filter_id & 0x01 ? CAN_MCAN_FCE_FIFO1 : CAN_MCAN_FCE_FIFO0;
|
||||
|
||||
err = can_mcan_write_mram(dev, CAN_MCAN_MRAM_OFFSET_STD_FILTER +
|
||||
err = can_mcan_write_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_STD_FILTER] +
|
||||
filter_id * sizeof(struct can_mcan_std_filter),
|
||||
&filter_element, sizeof(filter_element));
|
||||
if (err != 0) {
|
||||
|
@ -1008,39 +1024,24 @@ int can_mcan_add_rx_filter_std(const struct device *dev, can_rx_callback_t callb
|
|||
|
||||
LOG_DBG("Attached std filter at %d", filter_id);
|
||||
|
||||
if ((filter->flags & CAN_FILTER_RTR) != 0U) {
|
||||
data->std_filt_rtr |= (1U << filter_id);
|
||||
} else {
|
||||
data->std_filt_rtr &= ~(1U << filter_id);
|
||||
}
|
||||
|
||||
if ((filter->flags & (CAN_FILTER_DATA | CAN_FILTER_RTR)) !=
|
||||
(CAN_FILTER_DATA | CAN_FILTER_RTR)) {
|
||||
data->std_filt_rtr_mask |= (1U << filter_id);
|
||||
} else {
|
||||
data->std_filt_rtr_mask &= ~(1U << filter_id);
|
||||
}
|
||||
|
||||
if ((filter->flags & CAN_FILTER_FDF) != 0U) {
|
||||
data->std_filt_fd_frame |= (1U << filter_id);
|
||||
} else {
|
||||
data->std_filt_fd_frame &= ~(1U << filter_id);
|
||||
}
|
||||
|
||||
data->rx_cb_std[filter_id] = callback;
|
||||
data->cb_arg_std[filter_id] = user_data;
|
||||
__ASSERT_NO_MSG(filter_id <= cbs->num_std);
|
||||
cbs->std[filter_id].function = callback;
|
||||
cbs->std[filter_id].user_data = user_data;
|
||||
cbs->std[filter_id].flags = filter->flags;
|
||||
|
||||
return filter_id;
|
||||
}
|
||||
|
||||
static int can_mcan_get_free_ext(const struct device *dev)
|
||||
{
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
const struct can_mcan_callbacks *cbs = config->callbacks;
|
||||
struct can_mcan_ext_filter filter;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_EXT_FILTER_DATA; ++i) {
|
||||
err = can_mcan_read_mram(dev, CAN_MCAN_MRAM_OFFSET_EXT_FILTER +
|
||||
for (i = 0; i < cbs->num_ext; ++i) {
|
||||
err = can_mcan_read_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_EXT_FILTER] +
|
||||
i * sizeof(struct can_mcan_ext_filter), &filter,
|
||||
sizeof(struct can_mcan_ext_filter));
|
||||
if (err != 0) {
|
||||
|
@ -1059,6 +1060,8 @@ static int can_mcan_get_free_ext(const struct device *dev)
|
|||
static int can_mcan_add_rx_filter_ext(const struct device *dev, can_rx_callback_t callback,
|
||||
void *user_data, const struct can_filter *filter)
|
||||
{
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
const struct can_mcan_callbacks *cbs = config->callbacks;
|
||||
struct can_mcan_data *data = dev->data;
|
||||
struct can_mcan_ext_filter filter_element = {
|
||||
.id2 = filter->mask,
|
||||
|
@ -1080,7 +1083,7 @@ static int can_mcan_add_rx_filter_ext(const struct device *dev, can_rx_callback_
|
|||
/* TODO proper fifo balancing */
|
||||
filter_element.efce = filter_id & 0x01 ? CAN_MCAN_FCE_FIFO1 : CAN_MCAN_FCE_FIFO0;
|
||||
|
||||
err = can_mcan_write_mram(dev, CAN_MCAN_MRAM_OFFSET_EXT_FILTER +
|
||||
err = can_mcan_write_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_EXT_FILTER] +
|
||||
filter_id * sizeof(struct can_mcan_ext_filter),
|
||||
&filter_element, sizeof(filter_element));
|
||||
if (err != 0) {
|
||||
|
@ -1092,27 +1095,10 @@ static int can_mcan_add_rx_filter_ext(const struct device *dev, can_rx_callback_
|
|||
|
||||
LOG_DBG("Attached ext filter at %d", filter_id);
|
||||
|
||||
if ((filter->flags & CAN_FILTER_RTR) != 0U) {
|
||||
data->ext_filt_rtr |= (1U << filter_id);
|
||||
} else {
|
||||
data->ext_filt_rtr &= ~(1U << filter_id);
|
||||
}
|
||||
|
||||
if ((filter->flags & (CAN_FILTER_DATA | CAN_FILTER_RTR)) !=
|
||||
(CAN_FILTER_DATA | CAN_FILTER_RTR)) {
|
||||
data->ext_filt_rtr_mask |= (1U << filter_id);
|
||||
} else {
|
||||
data->ext_filt_rtr_mask &= ~(1U << filter_id);
|
||||
}
|
||||
|
||||
if ((filter->flags & CAN_FILTER_FDF) != 0U) {
|
||||
data->ext_filt_fd_frame |= (1U << filter_id);
|
||||
} else {
|
||||
data->ext_filt_fd_frame &= ~(1U << filter_id);
|
||||
}
|
||||
|
||||
data->rx_cb_ext[filter_id] = callback;
|
||||
data->cb_arg_ext[filter_id] = user_data;
|
||||
__ASSERT_NO_MSG(filter_id <= cbs->num_ext);
|
||||
cbs->ext[filter_id].function = callback;
|
||||
cbs->ext[filter_id].user_data = user_data;
|
||||
cbs->ext[filter_id].flags = filter->flags;
|
||||
|
||||
return filter_id;
|
||||
}
|
||||
|
@ -1120,6 +1106,8 @@ static int can_mcan_add_rx_filter_ext(const struct device *dev, can_rx_callback_
|
|||
int can_mcan_add_rx_filter(const struct device *dev, can_rx_callback_t callback, void *user_data,
|
||||
const struct can_filter *filter)
|
||||
{
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
const struct can_mcan_callbacks *cbs = config->callbacks;
|
||||
int filter_id;
|
||||
|
||||
if (callback == NULL) {
|
||||
|
@ -1139,7 +1127,7 @@ int can_mcan_add_rx_filter(const struct device *dev, can_rx_callback_t callback,
|
|||
if ((filter->flags & CAN_FILTER_IDE) != 0U) {
|
||||
filter_id = can_mcan_add_rx_filter_ext(dev, callback, user_data, filter);
|
||||
if (filter_id >= 0) {
|
||||
filter_id += NUM_STD_FILTER_DATA;
|
||||
filter_id += cbs->num_std;
|
||||
}
|
||||
} else {
|
||||
filter_id = can_mcan_add_rx_filter_std(dev, callback, user_data, filter);
|
||||
|
@ -1150,27 +1138,29 @@ int can_mcan_add_rx_filter(const struct device *dev, can_rx_callback_t callback,
|
|||
|
||||
void can_mcan_remove_rx_filter(const struct device *dev, int filter_id)
|
||||
{
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
const struct can_mcan_callbacks *cbs = config->callbacks;
|
||||
struct can_mcan_data *data = dev->data;
|
||||
int err;
|
||||
|
||||
k_mutex_lock(&data->lock, K_FOREVER);
|
||||
|
||||
if (filter_id >= NUM_STD_FILTER_DATA) {
|
||||
filter_id -= NUM_STD_FILTER_DATA;
|
||||
if (filter_id >= NUM_EXT_FILTER_DATA) {
|
||||
if (filter_id >= cbs->num_std) {
|
||||
filter_id -= cbs->num_std;
|
||||
if (filter_id >= cbs->num_ext) {
|
||||
LOG_ERR("Wrong filter id");
|
||||
k_mutex_unlock(&data->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
err = can_mcan_clear_mram(dev, CAN_MCAN_MRAM_OFFSET_EXT_FILTER +
|
||||
err = can_mcan_clear_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_EXT_FILTER] +
|
||||
filter_id * sizeof(struct can_mcan_ext_filter),
|
||||
sizeof(struct can_mcan_ext_filter));
|
||||
if (err != 0) {
|
||||
LOG_ERR("failed to clear ext filter element (err %d)", err);
|
||||
}
|
||||
} else {
|
||||
err = can_mcan_clear_mram(dev, CAN_MCAN_MRAM_OFFSET_STD_FILTER +
|
||||
err = can_mcan_clear_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_STD_FILTER] +
|
||||
filter_id * sizeof(struct can_mcan_std_filter),
|
||||
sizeof(struct can_mcan_std_filter));
|
||||
if (err != 0) {
|
||||
|
@ -1229,6 +1219,8 @@ unlock:
|
|||
|
||||
int can_mcan_configure_mram(const struct device *dev, uintptr_t mrba, uintptr_t mram)
|
||||
{
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
uint32_t addr;
|
||||
uint32_t reg;
|
||||
int err;
|
||||
|
||||
|
@ -1246,49 +1238,56 @@ int can_mcan_configure_mram(const struct device *dev, uintptr_t mrba, uintptr_t
|
|||
|
||||
can_mcan_enable_configuration_change(dev);
|
||||
|
||||
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_STD_FILTER) & CAN_MCAN_SIDFC_FLSSA) |
|
||||
FIELD_PREP(CAN_MCAN_SIDFC_LSS, NUM_STD_FILTER_ELEMENTS);
|
||||
addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_STD_FILTER];
|
||||
reg = (addr & CAN_MCAN_SIDFC_FLSSA) | FIELD_PREP(CAN_MCAN_SIDFC_LSS,
|
||||
config->mram_elements[CAN_MCAN_MRAM_CFG_STD_FILTER]);
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_SIDFC, reg);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_EXT_FILTER) & CAN_MCAN_XIDFC_FLESA) |
|
||||
FIELD_PREP(CAN_MCAN_XIDFC_LSS, NUM_EXT_FILTER_ELEMENTS);
|
||||
addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_EXT_FILTER];
|
||||
reg = (addr & CAN_MCAN_XIDFC_FLESA) | FIELD_PREP(CAN_MCAN_XIDFC_LSS,
|
||||
config->mram_elements[CAN_MCAN_MRAM_CFG_EXT_FILTER]);
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_XIDFC, reg);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_RX_FIFO0) & CAN_MCAN_RXF0C_F0SA) |
|
||||
FIELD_PREP(CAN_MCAN_RXF0C_F0S, NUM_RX_FIFO0_ELEMENTS);
|
||||
addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_RX_FIFO0];
|
||||
reg = (addr & CAN_MCAN_RXF0C_F0SA) | FIELD_PREP(CAN_MCAN_RXF0C_F0S,
|
||||
config->mram_elements[CAN_MCAN_MRAM_CFG_RX_FIFO0]);
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_RXF0C, reg);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_RX_FIFO1) & CAN_MCAN_RXF1C_F1SA) |
|
||||
FIELD_PREP(CAN_MCAN_RXF1C_F1S, NUM_RX_FIFO1_ELEMENTS);
|
||||
addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_RX_FIFO1];
|
||||
reg = (addr & CAN_MCAN_RXF1C_F1SA) | FIELD_PREP(CAN_MCAN_RXF1C_F1S,
|
||||
config->mram_elements[CAN_MCAN_MRAM_CFG_RX_FIFO1]);
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_RXF1C, reg);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_RX_BUFFER) & CAN_MCAN_RXBC_RBSA);
|
||||
addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_RX_BUFFER];
|
||||
reg = (addr & CAN_MCAN_RXBC_RBSA);
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_RXBC, reg);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_TX_EVENT_FIFO) & CAN_MCAN_TXEFC_EFSA) |
|
||||
FIELD_PREP(CAN_MCAN_TXEFC_EFS, NUM_TX_EVENT_FIFO_ELEMENTS);
|
||||
addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_TX_EVENT_FIFO];
|
||||
reg = (addr & CAN_MCAN_TXEFC_EFSA) | FIELD_PREP(CAN_MCAN_TXEFC_EFS,
|
||||
config->mram_elements[CAN_MCAN_MRAM_CFG_TX_EVENT_FIFO]);
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_TXEFC, reg);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_TX_BUFFER) & CAN_MCAN_TXBC_TBSA) |
|
||||
FIELD_PREP(CAN_MCAN_TXBC_TFQS, NUM_TX_BUF_ELEMENTS) | CAN_MCAN_TXBC_TFQM;
|
||||
addr = mram - mrba + config->mram_offsets[CAN_MCAN_MRAM_CFG_TX_BUFFER];
|
||||
reg = (addr & CAN_MCAN_TXBC_TBSA) | FIELD_PREP(CAN_MCAN_TXBC_TFQS,
|
||||
config->mram_elements[CAN_MCAN_MRAM_CFG_TX_BUFFER]) | CAN_MCAN_TXBC_TFQM;
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_TXBC, reg);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
|
@ -1314,6 +1313,7 @@ int can_mcan_configure_mram(const struct device *dev, uintptr_t mrba, uintptr_t
|
|||
int can_mcan_init(const struct device *dev)
|
||||
{
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
const struct can_mcan_callbacks *cbs = config->callbacks;
|
||||
struct can_mcan_data *data = dev->data;
|
||||
struct can_timing timing;
|
||||
#ifdef CONFIG_CAN_FD_MODE
|
||||
|
@ -1327,10 +1327,15 @@ int can_mcan_init(const struct device *dev)
|
|||
__ASSERT_NO_MSG(config->ops->read_mram != NULL);
|
||||
__ASSERT_NO_MSG(config->ops->write_mram != NULL);
|
||||
__ASSERT_NO_MSG(config->ops->clear_mram != NULL);
|
||||
__ASSERT_NO_MSG(config->callbacks != NULL);
|
||||
|
||||
__ASSERT_NO_MSG(cbs->num_tx <= config->mram_elements[CAN_MCAN_MRAM_CFG_TX_BUFFER]);
|
||||
__ASSERT_NO_MSG(cbs->num_std <= config->mram_elements[CAN_MCAN_MRAM_CFG_STD_FILTER]);
|
||||
__ASSERT_NO_MSG(cbs->num_ext <= config->mram_elements[CAN_MCAN_MRAM_CFG_EXT_FILTER]);
|
||||
|
||||
k_mutex_init(&data->lock);
|
||||
k_mutex_init(&data->tx_mtx);
|
||||
k_sem_init(&data->tx_sem, NUM_TX_BUF_ELEMENTS, NUM_TX_BUF_ELEMENTS);
|
||||
k_sem_init(&data->tx_sem, cbs->num_tx, cbs->num_tx);
|
||||
|
||||
if (config->phy != NULL) {
|
||||
if (!device_is_ready(config->phy)) {
|
||||
|
@ -1503,5 +1508,5 @@ int can_mcan_init(const struct device *dev)
|
|||
return err;
|
||||
}
|
||||
|
||||
return can_mcan_clear_mram(dev, 0, sizeof(struct can_mcan_msg_sram));
|
||||
return can_mcan_clear_mram(dev, 0, config->mram_size);
|
||||
}
|
||||
|
|
|
@ -384,27 +384,34 @@
|
|||
#define CAN_MCAN_TXEFA 0x0F8
|
||||
#define CAN_MCAN_TXEFA_EFAI GENMASK(4, 0)
|
||||
|
||||
#ifdef CONFIG_CAN_MCUX_MCAN
|
||||
#define MCAN_DT_PATH DT_NODELABEL(can0)
|
||||
#else
|
||||
#define MCAN_DT_PATH DT_PATH(soc, can)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Indexes for the cells in the devicetree bosch,mram-cfg property. These match the
|
||||
* description of the cells in the bosch,m_can-base devicetree binding.
|
||||
* @name Indexes for the cells in the devicetree bosch,mram-cfg property
|
||||
* @anchor CAN_MCAN_MRAM_CFG
|
||||
|
||||
* These match the description of the cells in the bosch,m_can-base devicetree binding.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
enum can_mcan_mram_cfg {
|
||||
CAN_MCAN_MRAM_CFG_OFFSET = 0,
|
||||
CAN_MCAN_MRAM_CFG_STD_FILTER,
|
||||
CAN_MCAN_MRAM_CFG_EXT_FILTER,
|
||||
CAN_MCAN_MRAM_CFG_RX_FIFO0,
|
||||
CAN_MCAN_MRAM_CFG_RX_FIFO1,
|
||||
CAN_MCAN_MRAM_CFG_RX_BUFFER,
|
||||
CAN_MCAN_MRAM_CFG_TX_EVENT,
|
||||
CAN_MCAN_MRAM_CFG_TX_BUFFER,
|
||||
CAN_MCAN_MRAM_CFG_NUM_CELLS
|
||||
};
|
||||
/** offset cell index */
|
||||
#define CAN_MCAN_MRAM_CFG_OFFSET 0
|
||||
/** std-filter-elements cell index */
|
||||
#define CAN_MCAN_MRAM_CFG_STD_FILTER 1
|
||||
/** ext-filter-elements cell index */
|
||||
#define CAN_MCAN_MRAM_CFG_EXT_FILTER 2
|
||||
/** rx-fifo0-elements cell index */
|
||||
#define CAN_MCAN_MRAM_CFG_RX_FIFO0 3
|
||||
/** rx-fifo1-elements cell index */
|
||||
#define CAN_MCAN_MRAM_CFG_RX_FIFO1 4
|
||||
/** rx-buffer-elements cell index */
|
||||
#define CAN_MCAN_MRAM_CFG_RX_BUFFER 5
|
||||
/** tx-event-fifo-elements cell index */
|
||||
#define CAN_MCAN_MRAM_CFG_TX_EVENT_FIFO 6
|
||||
/** tx-buffer-elements cell index */
|
||||
#define CAN_MCAN_MRAM_CFG_TX_BUFFER 7
|
||||
/** Total number of cells in bosch,mram-cfg property */
|
||||
#define CAN_MCAN_MRAM_CFG_NUM_CELLS 8
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Get the Bosch M_CAN Message RAM offset
|
||||
|
@ -412,8 +419,8 @@ enum can_mcan_mram_cfg {
|
|||
* @param node_id node identifier
|
||||
* @return the Message RAM offset in bytes
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_OFFSET(node_id) \
|
||||
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 0)
|
||||
#define CAN_MCAN_DT_MRAM_OFFSET(node_id) \
|
||||
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, CAN_MCAN_MRAM_CFG_OFFSET)
|
||||
|
||||
/**
|
||||
* @brief Get the number of standard (11-bit) filter elements in Bosch M_CAN Message RAM
|
||||
|
@ -421,8 +428,8 @@ enum can_mcan_mram_cfg {
|
|||
* @param node_id node identifier
|
||||
* @return the number of standard (11-bit) filter elements
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_STD_FILTER_ELEM(node_id) \
|
||||
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 1)
|
||||
#define CAN_MCAN_DT_MRAM_STD_FILTER_ELEMENTS(node_id) \
|
||||
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, CAN_MCAN_MRAM_CFG_STD_FILTER)
|
||||
|
||||
/**
|
||||
* @brief Get the number of extended (29-bit) filter elements in Bosch M_CAN Message RAM
|
||||
|
@ -430,8 +437,8 @@ enum can_mcan_mram_cfg {
|
|||
* @param node_id node identifier
|
||||
* @return the number of extended (29-bit) filter elements
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_EXT_FILTER_ELEM(node_id) \
|
||||
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 2)
|
||||
#define CAN_MCAN_DT_MRAM_EXT_FILTER_ELEMENTS(node_id) \
|
||||
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, CAN_MCAN_MRAM_CFG_EXT_FILTER)
|
||||
|
||||
/**
|
||||
* @brief Get the number of Rx FIFO 0 elements in Bosch M_CAN Message RAM
|
||||
|
@ -439,8 +446,8 @@ enum can_mcan_mram_cfg {
|
|||
* @param node_id node identifier
|
||||
* @return the number of Rx FIFO 0 elements
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_RX_FIFO0_ELEM(node_id) \
|
||||
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 3)
|
||||
#define CAN_MCAN_DT_MRAM_RX_FIFO0_ELEMENTS(node_id) \
|
||||
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, CAN_MCAN_MRAM_CFG_RX_FIFO0)
|
||||
|
||||
/**
|
||||
* @brief Get the number of Rx FIFO 1 elements in Bosch M_CAN Message RAM
|
||||
|
@ -448,8 +455,8 @@ enum can_mcan_mram_cfg {
|
|||
* @param node_id node identifier
|
||||
* @return the number of Rx FIFO 1 elements
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_RX_FIFO1_ELEM(node_id) \
|
||||
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 4)
|
||||
#define CAN_MCAN_DT_MRAM_RX_FIFO1_ELEMENTS(node_id) \
|
||||
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, CAN_MCAN_MRAM_CFG_RX_FIFO1)
|
||||
|
||||
/**
|
||||
* @brief Get the number of Rx Buffer elements in Bosch M_CAN Message RAM
|
||||
|
@ -457,8 +464,8 @@ enum can_mcan_mram_cfg {
|
|||
* @param node_id node identifier
|
||||
* @return the number of Rx Buffer elements
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_RX_BUFFER_ELEM(node_id) \
|
||||
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 5)
|
||||
#define CAN_MCAN_DT_MRAM_RX_BUFFER_ELEMENTS(node_id) \
|
||||
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, CAN_MCAN_MRAM_CFG_RX_BUFFER)
|
||||
|
||||
/**
|
||||
* @brief Get the number of Tx Event FIFO elements in Bosch M_CAN Message RAM
|
||||
|
@ -466,8 +473,8 @@ enum can_mcan_mram_cfg {
|
|||
* @param node_id node identifier
|
||||
* @return the number of Tx Event FIFO elements
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEM(node_id) \
|
||||
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 6)
|
||||
#define CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEMENTS(node_id) \
|
||||
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, CAN_MCAN_MRAM_CFG_TX_EVENT_FIFO)
|
||||
|
||||
/**
|
||||
* @brief Get the number of Tx Buffer elements in Bosch M_CAN Message RAM
|
||||
|
@ -475,8 +482,163 @@ enum can_mcan_mram_cfg {
|
|||
* @param node_id node identifier
|
||||
* @return the number of Tx Buffer elements
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_TX_BUFFER_ELEM(node_id) \
|
||||
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, 7)
|
||||
#define CAN_MCAN_DT_MRAM_TX_BUFFER_ELEMENTS(node_id) \
|
||||
DT_PROP_BY_IDX(node_id, bosch_mram_cfg, CAN_MCAN_MRAM_CFG_TX_BUFFER)
|
||||
|
||||
/**
|
||||
* @brief Get the base offset of standard (11-bit) filter elements in Bosch M_CAN Message RAM
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @return the base offset of standard (11-bit) filter elements in bytes
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_STD_FILTER_OFFSET(node_id) (0U)
|
||||
|
||||
/**
|
||||
* @brief Get the base offset of extended (29-bit) filter elements in Bosch M_CAN Message RAM
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @return the base offset of extended (29-bit) filter elements in bytes
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_EXT_FILTER_OFFSET(node_id) \
|
||||
(CAN_MCAN_DT_MRAM_STD_FILTER_OFFSET(node_id) + \
|
||||
CAN_MCAN_DT_MRAM_STD_FILTER_ELEMENTS(node_id) * sizeof(struct can_mcan_std_filter))
|
||||
|
||||
/**
|
||||
* @brief Get the base offset of Rx FIFO 0 elements in Bosch M_CAN Message RAM
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @return the base offset of Rx FIFO 0 elements in bytes
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_RX_FIFO0_OFFSET(node_id) \
|
||||
(CAN_MCAN_DT_MRAM_EXT_FILTER_OFFSET(node_id) + \
|
||||
CAN_MCAN_DT_MRAM_EXT_FILTER_ELEMENTS(node_id) * sizeof(struct can_mcan_ext_filter))
|
||||
|
||||
/**
|
||||
* @brief Get the base offset of Rx FIFO 1 elements in Bosch M_CAN Message RAM
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @return the base offset of Rx FIFO 1 elements in bytes
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_RX_FIFO1_OFFSET(node_id) \
|
||||
(CAN_MCAN_DT_MRAM_RX_FIFO0_OFFSET(node_id) + \
|
||||
CAN_MCAN_DT_MRAM_RX_FIFO0_ELEMENTS(node_id) * sizeof(struct can_mcan_rx_fifo))
|
||||
|
||||
/**
|
||||
* @brief Get the base offset of Rx Buffer elements in Bosch M_CAN Message RAM
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @return the base offset of Rx Buffer elements in bytes
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_RX_BUFFER_OFFSET(node_id) \
|
||||
(CAN_MCAN_DT_MRAM_RX_FIFO1_OFFSET(node_id) + \
|
||||
CAN_MCAN_DT_MRAM_RX_FIFO1_ELEMENTS(node_id) * sizeof(struct can_mcan_rx_fifo))
|
||||
|
||||
/**
|
||||
* @brief Get the base offset of Tx Event FIFO elements in Bosch M_CAN Message RAM
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @return the base offset of Tx Event FIFO elements in bytes
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_OFFSET(node_id) \
|
||||
(CAN_MCAN_DT_MRAM_RX_BUFFER_OFFSET(node_id) + \
|
||||
CAN_MCAN_DT_MRAM_RX_BUFFER_ELEMENTS(node_id) * sizeof(struct can_mcan_rx_fifo))
|
||||
|
||||
/**
|
||||
* @brief Get the base offset of Tx Buffer elements in Bosch M_CAN Message RAM
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @return the base offset of Tx Buffer elements in bytes
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_TX_BUFFER_OFFSET(node_id) \
|
||||
(CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_OFFSET(node_id) + \
|
||||
CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEMENTS(node_id) * sizeof(struct can_mcan_tx_event_fifo))
|
||||
|
||||
/**
|
||||
* @brief Get the Bosch M_CAN register base address
|
||||
*
|
||||
* For devicetree nodes with just one register block, this macro returns the base address of that
|
||||
* register block.
|
||||
*
|
||||
* If a devicetree node has more than one register block, this macros returns the base address of
|
||||
* the register block named "m_can".
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @return the Bosch M_CAN register base address
|
||||
*/
|
||||
#define CAN_MCAN_DT_MCAN_ADDR(node_id) \
|
||||
COND_CODE_1(DT_NUM_REGS(node_id), ((mm_reg_t)DT_REG_ADDR(node_id)), \
|
||||
((mm_reg_t)DT_REG_ADDR_BY_NAME(node_id, m_can)))
|
||||
|
||||
/**
|
||||
* @brief Get the Bosch M_CAN Message RAM base address
|
||||
*
|
||||
* For devicetree nodes with dedicated Message RAM area defined via devicetree, this macro returns
|
||||
* the base address of the Message RAM, taking in the Message RAM offset into account.
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @return the Bosch M_CAN Message RAM base address
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_ADDR(node_id) \
|
||||
(mem_addr_t)(DT_REG_ADDR_BY_NAME(node_id, message_ram) + CAN_MCAN_DT_MRAM_OFFSET(node_id))
|
||||
|
||||
/**
|
||||
* @brief Get the Bosch M_CAN Message RAM size
|
||||
*
|
||||
* For devicetree nodes with dedicated Message RAM area defined via devicetree, this macro returns
|
||||
* the size of the Message RAM, taking in the Message RAM offset into account.
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @return the Bosch M_CAN Message RAM base address
|
||||
* @see CAN_MCAN_DT_MRAM_ELEMENTS_SIZE()
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_SIZE(node_id) \
|
||||
(mem_addr_t)(DT_REG_SIZE_BY_NAME(node_id, message_ram) - CAN_MCAN_DT_MRAM_OFFSET(node_id))
|
||||
|
||||
/**
|
||||
* @brief Get the total size of all Bosch M_CAN Message RAM elements
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @return the total size of all Message RAM elements in bytes
|
||||
* @see CAN_MCAN_DT_MRAM_SIZE()
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_ELEMENTS_SIZE(node_id) \
|
||||
(CAN_MCAN_DT_MRAM_TX_BUFFER_OFFSET(node_id) + \
|
||||
CAN_MCAN_DT_MRAM_TX_BUFFER_ELEMENTS(node_id) * sizeof(struct can_mcan_tx_buffer))
|
||||
|
||||
/**
|
||||
* @brief Define a RAM buffer for Bosch M_CAN Message RAM
|
||||
*
|
||||
* For devicetree nodes without dedicated Message RAM area, this macro defines a suitable RAM buffer
|
||||
* to hold the Message RAM elements. Since this buffer cannot be shared between multiple Bosch M_CAN
|
||||
* instances, the Message RAM offset must be set to 0x0.
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @param _name buffer variable name
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_DEFINE(node_id, _name) \
|
||||
BUILD_ASSERT(CAN_MCAN_DT_MRAM_OFFSET(node_id) == 0, "offset must be 0"); \
|
||||
static char __noinit __nocache __aligned(4) _name[CAN_MCAN_DT_MRAM_ELEMENTS_SIZE(node_id)];
|
||||
|
||||
/**
|
||||
* @brief Assert that the Message RAM configuration meets the Bosch M_CAN IP core restrictions
|
||||
*
|
||||
* @param node_id node identifier
|
||||
*/
|
||||
#define CAN_MCAN_DT_BUILD_ASSERT_MRAM_CFG(node_id) \
|
||||
BUILD_ASSERT(CAN_MCAN_DT_MRAM_STD_FILTER_ELEMENTS(node_id) <= 128, \
|
||||
"Maximum Standard filter elements exceeded"); \
|
||||
BUILD_ASSERT(CAN_MCAN_DT_MRAM_EXT_FILTER_ELEMENTS(node_id) <= 64, \
|
||||
"Maximum Extended filter elements exceeded"); \
|
||||
BUILD_ASSERT(CAN_MCAN_DT_MRAM_RX_FIFO0_ELEMENTS(node_id) <= 64, \
|
||||
"Maximum Rx FIFO 0 elements exceeded"); \
|
||||
BUILD_ASSERT(CAN_MCAN_DT_MRAM_RX_FIFO1_ELEMENTS(node_id) <= 64, \
|
||||
"Maximum Rx FIFO 1 elements exceeded"); \
|
||||
BUILD_ASSERT(CAN_MCAN_DT_MRAM_RX_BUFFER_ELEMENTS(node_id) <= 64, \
|
||||
"Maximum Rx Buffer elements exceeded"); \
|
||||
BUILD_ASSERT(CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEMENTS(node_id) <= 32, \
|
||||
"Maximum Tx Buffer elements exceeded"); \
|
||||
BUILD_ASSERT(CAN_MCAN_DT_MRAM_TX_BUFFER_ELEMENTS(node_id) <= 32, \
|
||||
"Maximum Tx Buffer elements exceeded");
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_OFFSET(DT_DRV_INST(inst))
|
||||
|
@ -484,96 +646,181 @@ enum can_mcan_mram_cfg {
|
|||
* @return the Message RAM offset in bytes
|
||||
* @see CAN_MCAN_DT_MRAM_OFFSET()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_OFFSET(inst) \
|
||||
CAN_MCAN_DT_MRAM_OFFSET(DT_DRV_INST(inst))
|
||||
#define CAN_MCAN_DT_INST_MRAM_OFFSET(inst) CAN_MCAN_DT_MRAM_OFFSET(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_STD_FILTER_ELEM(DT_DRV_INST(inst))
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_STD_FILTER_ELEMENTS(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the number of standard (11-bit) elements
|
||||
* @see CAN_MCAN_DT_MRAM_STD_FILTER_ELEM()
|
||||
* @see CAN_MCAN_DT_MRAM_STD_FILTER_ELEMENTS()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_STD_FILTER_ELEM(inst) \
|
||||
CAN_MCAN_DT_MRAM_STD_FILTER_ELEMDT_DRV_INST(inst))
|
||||
#define CAN_MCAN_DT_INST_MRAM_STD_FILTER_ELEMENTS(inst) \
|
||||
CAN_MCAN_DT_MRAM_STD_FILTER_ELEMENTS(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_EXT_FILTER_ELEM(DT_DRV_INST(inst))
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_EXT_FILTER_ELEMENTS(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the number of extended (29-bit) elements
|
||||
* @see CAN_MCAN_DT_MRAM_EXT_FILTER_ELEM()
|
||||
* @see CAN_MCAN_DT_MRAM_EXT_FILTER_ELEMENTS()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_EXT_FILTER_ELEM(inst) \
|
||||
CAN_MCAN_DT_MRAM_EXT_FILTER_ELEM(DT_DRV_INST(inst))
|
||||
#define CAN_MCAN_DT_INST_MRAM_EXT_FILTER_ELEMENTS(inst) \
|
||||
CAN_MCAN_DT_MRAM_EXT_FILTER_ELEMENTS(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_FIFO0_ELEM(DT_DRV_INST(inst))
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_FIFO0_ELEMENTS(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the number of Rx FIFO 0 elements
|
||||
* @see CAN_MCAN_DT_MRAM_RX_FIFO0_ELEM()
|
||||
* @see CAN_MCAN_DT_MRAM_RX_FIFO0_ELEMENTS()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_RX_FIFO0_ELEM(inst) \
|
||||
CAN_MCAN_DT_MRAM_RX_FIFO0_ELEM(DT_DRV_INST(inst))
|
||||
#define CAN_MCAN_DT_INST_MRAM_RX_FIFO0_ELEMENTS(inst) \
|
||||
CAN_MCAN_DT_MRAM_RX_FIFO0_ELEMENTS(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_FIFO1_ELEM(DT_DRV_INST(inst))
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_FIFO1_ELEMENTS(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the number of Rx FIFO 1 elements
|
||||
* @see CAN_MCAN_DT_MRAM_RX_FIFO1_ELEM()
|
||||
* @see CAN_MCAN_DT_MRAM_RX_FIFO1_ELEMENTS()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_RX_FIFO1_ELEM(inst) \
|
||||
CAN_MCAN_DT_MRAM_RX_FIFO1_ELEM(DT_DRV_INST(inst))
|
||||
#define CAN_MCAN_DT_INST_MRAM_RX_FIFO1_ELEMENTS(inst) \
|
||||
CAN_MCAN_DT_MRAM_RX_FIFO1_ELEMENTS(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_BUFFER_ELEM(DT_DRV_INST(inst))
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_BUFFER_ELEMENTS(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the number of Rx Buffer elements
|
||||
* @see CAN_MCAN_DT_MRAM_RX_BUFFER_ELEM()
|
||||
* @see CAN_MCAN_DT_MRAM_RX_BUFFER_ELEMENTS()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_RX_BUFFER_ELEM(inst) \
|
||||
CAN_MCAN_DT_MRAM_RX_BUFFER_ELEM(DT_DRV_INST(inst))
|
||||
#define CAN_MCAN_DT_INST_MRAM_RX_BUFFER_ELEMENTS(inst) \
|
||||
CAN_MCAN_DT_MRAM_RX_BUFFER_ELEMENTS(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_TX_EVENT_ELEM(DT_DRV_INST(inst))
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEMENTS(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the number of Tx Event FIFO elements
|
||||
* @see CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEM()
|
||||
* @see CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEMENTS()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_TX_EVENT_FIFO_ELEM(inst) \
|
||||
CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEM(DT_DRV_INST(inst))
|
||||
#define CAN_MCAN_DT_INST_MRAM_TX_EVENT_FIFO_ELEMENTS(inst) \
|
||||
CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEMENTS(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_TX_BUFFER_ELEM(DT_DRV_INST(inst))
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_TX_BUFFER_ELEMENTS(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the number of Tx Buffer elements
|
||||
* @see CAN_MCAN_DT_MRAM_TX_BUFFER_ELEM()
|
||||
* @see CAN_MCAN_DT_MRAM_TX_BUFFER_ELEMENTS()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_TX_BUFFER_ELEM(inst) \
|
||||
CAN_MCAN_DT_MRAM_TX_BUFFER_ELEM(DT_DRV_INST(inst))
|
||||
#define CAN_MCAN_DT_INST_MRAM_TX_BUFFER_ELEMENTS(inst) \
|
||||
CAN_MCAN_DT_MRAM_TX_BUFFER_ELEMENTS(DT_DRV_INST(inst))
|
||||
|
||||
#define NUM_STD_FILTER_ELEMENTS CAN_MCAN_DT_MRAM_STD_FILTER_ELEM(MCAN_DT_PATH)
|
||||
#define NUM_EXT_FILTER_ELEMENTS CAN_MCAN_DT_MRAM_EXT_FILTER_ELEM(MCAN_DT_PATH)
|
||||
#define NUM_RX_FIFO0_ELEMENTS CAN_MCAN_DT_MRAM_RX_FIFO0_ELEM(MCAN_DT_PATH)
|
||||
#define NUM_RX_FIFO1_ELEMENTS CAN_MCAN_DT_MRAM_RX_FIFO1_ELEM(MCAN_DT_PATH)
|
||||
#define NUM_RX_BUF_ELEMENTS CAN_MCAN_DT_MRAM_RX_BUFFER_ELEM(MCAN_DT_PATH)
|
||||
#define NUM_TX_EVENT_FIFO_ELEMENTS CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEM(MCAN_DT_PATH)
|
||||
#define NUM_TX_BUF_ELEMENTS CAN_MCAN_DT_MRAM_TX_BUFFER_ELEM(MCAN_DT_PATH)
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_STD_FILTER_OFFSET(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the base offset of standard (11-bit) filter elements in bytes
|
||||
* @see CAN_MCAN_DT_MRAM_STD_FILTER_OFFSET()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_STD_FILTER_OFFSET(inst) \
|
||||
CAN_MCAN_DT_MRAM_STD_FILTER_OFFSET(DT_DRV_INST(inst))
|
||||
|
||||
/* Assert that the Message RAM configuration meets the M_CAN IP core restrictions */
|
||||
BUILD_ASSERT(NUM_STD_FILTER_ELEMENTS <= 128, "Maximum Standard filter elements exceeded");
|
||||
BUILD_ASSERT(NUM_EXT_FILTER_ELEMENTS <= 64, "Maximum Extended filter elements exceeded");
|
||||
BUILD_ASSERT(NUM_RX_FIFO0_ELEMENTS <= 64, "Maximum Rx FIFO 0 elements exceeded");
|
||||
BUILD_ASSERT(NUM_RX_FIFO1_ELEMENTS <= 64, "Maximum Rx FIFO 1 elements exceeded");
|
||||
BUILD_ASSERT(NUM_RX_BUF_ELEMENTS <= 64, "Maximum Rx Buffer elements exceeded");
|
||||
BUILD_ASSERT(NUM_TX_EVENT_FIFO_ELEMENTS <= 32, "Maximum Tx Buffer elements exceeded");
|
||||
BUILD_ASSERT(NUM_TX_BUF_ELEMENTS <= 32, "Maximum Tx Buffer elements exceeded");
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_EXT_FILTER_OFFSET(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the base offset of extended (29-bit) filter elements in bytes
|
||||
* @see CAN_MCAN_DT_MRAM_EXT_FILTER_OFFSET()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_EXT_FILTER_OFFSET(inst) \
|
||||
CAN_MCAN_DT_MRAM_EXT_FILTER_OFFSET(DT_DRV_INST(inst))
|
||||
|
||||
#ifdef CONFIG_CAN_STM32FD
|
||||
#define NUM_STD_FILTER_DATA CONFIG_CAN_MAX_STD_ID_FILTER
|
||||
#define NUM_EXT_FILTER_DATA CONFIG_CAN_MAX_EXT_ID_FILTER
|
||||
#else
|
||||
#define NUM_STD_FILTER_DATA NUM_STD_FILTER_ELEMENTS
|
||||
#define NUM_EXT_FILTER_DATA NUM_EXT_FILTER_ELEMENTS
|
||||
#endif
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_FIFO0_OFFSET(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the base offset of Rx FIFO 0 elements in bytes
|
||||
* @see CAN_MCAN_DT_MRAM_RX_FIFO0_OFFSET()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_RX_FIFO0_OFFSET(inst) \
|
||||
CAN_MCAN_DT_MRAM_RX_FIFO0_OFFSET(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_FIFO1_OFFSET(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the base offset of Rx FIFO 1 elements in bytes
|
||||
* @see CAN_MCAN_DT_MRAM_RX_FIFO1_OFFSET()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_RX_FIFO1_OFFSET(inst) \
|
||||
CAN_MCAN_DT_MRAM_RX_FIFO1_OFFSET(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_BUFFER_OFFSET(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the base offset of Rx Buffer elements in bytes
|
||||
* @see CAN_MCAN_DT_MRAM_RX_BUFFER_OFFSET()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_RX_BUFFER_OFFSET(inst) \
|
||||
CAN_MCAN_DT_MRAM_RX_BUFFER_OFFSET(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_OFFSET(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the base offset of Tx Event FIFO elements in bytes
|
||||
* @see CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_OFFSET()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_TX_EVENT_FIFO_OFFSET(inst) \
|
||||
CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_OFFSET(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_TX_BUFFER_OFFSET(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the base offset of Tx Buffer elements in bytes
|
||||
* @see CAN_MCAN_DT_MRAM_TX_BUFFER_OFFSET()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_TX_BUFFER_OFFSET(inst) \
|
||||
CAN_MCAN_DT_MRAM_TX_BUFFER_OFFSET(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MCAN_ADDR(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the Bosch M_CAN register base address
|
||||
* @see CAN_MCAN_DT_MRAM_ADDR()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MCAN_ADDR(inst) CAN_MCAN_DT_MCAN_ADDR(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_ADDR(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the Bosch M_CAN Message RAM base address
|
||||
* @see CAN_MCAN_DT_MRAM_ADDR()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_ADDR(inst) CAN_MCAN_DT_MRAM_ADDR(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_SIZE(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the Bosch M_CAN Message RAM size in bytes
|
||||
* @see CAN_MCAN_DT_MRAM_SIZE()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_SIZE(inst) CAN_MCAN_DT_MRAM_SIZE(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_ELEMENTS_SIZE(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @return the total size of all Message RAM elements in bytes
|
||||
* @see CAN_MCAN_DT_MRAM_ELEMENTS_SIZE()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_ELEMENTS_SIZE(inst) CAN_MCAN_DT_MRAM_ELEMENTS_SIZE(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_DEFINE(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @param _name buffer variable name
|
||||
* @see CAN_MCAN_DT_MRAM_DEFINE()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_DEFINE(inst, _name) CAN_MCAN_DT_MRAM_DEFINE(DT_DRV_INST(inst), _name)
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_BUILD_ASSERT_MRAM_CFG(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @see CAN_MCAN_DT_BUILD_ASSERT_MRAM_CFG()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_BUILD_ASSERT_MRAM_CFG(inst) \
|
||||
CAN_MCAN_DT_BUILD_ASSERT_MRAM_CFG(DT_DRV_INST(inst))
|
||||
|
||||
struct can_mcan_rx_fifo_hdr {
|
||||
union {
|
||||
|
@ -689,42 +936,12 @@ struct can_mcan_ext_filter {
|
|||
uint32_t eft: 2; /* Filter type */
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct can_mcan_msg_sram {
|
||||
struct can_mcan_std_filter std_filt[NUM_STD_FILTER_ELEMENTS];
|
||||
struct can_mcan_ext_filter ext_filt[NUM_EXT_FILTER_ELEMENTS];
|
||||
struct can_mcan_rx_fifo rx_fifo0[NUM_RX_FIFO0_ELEMENTS];
|
||||
struct can_mcan_rx_fifo rx_fifo1[NUM_RX_FIFO1_ELEMENTS];
|
||||
struct can_mcan_rx_fifo rx_buffer[NUM_RX_BUF_ELEMENTS];
|
||||
struct can_mcan_tx_event_fifo tx_event_fifo[NUM_TX_EVENT_FIFO_ELEMENTS];
|
||||
struct can_mcan_tx_buffer tx_buffer[NUM_TX_BUF_ELEMENTS];
|
||||
} __packed __aligned(4);
|
||||
|
||||
#define CAN_MCAN_MRAM_OFFSET_STD_FILTER offsetof(struct can_mcan_msg_sram, std_filt)
|
||||
#define CAN_MCAN_MRAM_OFFSET_EXT_FILTER offsetof(struct can_mcan_msg_sram, ext_filt)
|
||||
#define CAN_MCAN_MRAM_OFFSET_RX_FIFO0 offsetof(struct can_mcan_msg_sram, rx_fifo0)
|
||||
#define CAN_MCAN_MRAM_OFFSET_RX_FIFO1 offsetof(struct can_mcan_msg_sram, rx_fifo1)
|
||||
#define CAN_MCAN_MRAM_OFFSET_RX_BUFFER offsetof(struct can_mcan_msg_sram, rx_buffer)
|
||||
#define CAN_MCAN_MRAM_OFFSET_TX_EVENT_FIFO offsetof(struct can_mcan_msg_sram, tx_event_fifo)
|
||||
#define CAN_MCAN_MRAM_OFFSET_TX_BUFFER offsetof(struct can_mcan_msg_sram, tx_buffer)
|
||||
|
||||
struct can_mcan_data {
|
||||
struct k_mutex lock;
|
||||
struct k_sem tx_sem;
|
||||
struct k_mutex tx_mtx;
|
||||
can_tx_callback_t tx_fin_cb[NUM_TX_BUF_ELEMENTS];
|
||||
void *tx_fin_cb_arg[NUM_TX_BUF_ELEMENTS];
|
||||
can_rx_callback_t rx_cb_std[NUM_STD_FILTER_DATA];
|
||||
can_rx_callback_t rx_cb_ext[NUM_EXT_FILTER_DATA];
|
||||
void *cb_arg_std[NUM_STD_FILTER_DATA];
|
||||
void *cb_arg_ext[NUM_EXT_FILTER_DATA];
|
||||
can_state_change_callback_t state_change_cb;
|
||||
void *state_change_cb_data;
|
||||
uint32_t std_filt_fd_frame;
|
||||
uint32_t std_filt_rtr;
|
||||
uint32_t std_filt_rtr_mask;
|
||||
uint16_t ext_filt_fd_frame;
|
||||
uint16_t ext_filt_rtr;
|
||||
uint16_t ext_filt_rtr_mask;
|
||||
bool started;
|
||||
#ifdef CONFIG_CAN_FD_MODE
|
||||
bool fd;
|
||||
|
@ -814,8 +1031,90 @@ struct can_mcan_ops {
|
|||
can_mcan_clear_mram_t clear_mram;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Bosch M_CAN driver internal Tx callback structure.
|
||||
*/
|
||||
struct can_mcan_tx_callback {
|
||||
can_tx_callback_t function;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Bosch M_CAN driver internal Rx callback structure.
|
||||
*/
|
||||
struct can_mcan_rx_callback {
|
||||
can_rx_callback_t function;
|
||||
void *user_data;
|
||||
uint8_t flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Bosch M_CAN driver internal Tx + Rx callbacks structure.
|
||||
*/
|
||||
struct can_mcan_callbacks {
|
||||
struct can_mcan_tx_callback *tx;
|
||||
struct can_mcan_rx_callback *std;
|
||||
struct can_mcan_rx_callback *ext;
|
||||
uint8_t num_tx;
|
||||
uint8_t num_std;
|
||||
uint8_t num_ext;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Define Bosch M_CAN TX and RX callbacks
|
||||
*
|
||||
* This macro allows a Bosch M_CAN driver frontend using a fixed Message RAM configuration to limit
|
||||
* the required software resources (e.g. limit the number of the standard (11-bit) or extended
|
||||
* (29-bit) filters in use).
|
||||
*
|
||||
* Frontend drivers supporting dynamic Message RAM configuration should use @ref
|
||||
* CAN_MCAN_DT_CALLBACKS_DEFINE() or @ref CAN_MCAN_DT_INST_CALLBACKS_DEFINE() instead.
|
||||
*
|
||||
* @param _name callbacks variable name
|
||||
* @param _tx Number of Tx callbacks
|
||||
* @param _std Number of standard (11-bit) filter callbacks
|
||||
* @param _ext Number of extended (29-bit) filter callbacks
|
||||
* @see CAN_MCAN_DT_CALLBACKS_DEFINE()
|
||||
*/
|
||||
#define CAN_MCAN_CALLBACKS_DEFINE(_name, _tx, _std, _ext) \
|
||||
static struct can_mcan_tx_callback _name##_tx_cbs[_tx]; \
|
||||
static struct can_mcan_rx_callback _name##_std_cbs[_std]; \
|
||||
static struct can_mcan_rx_callback _name##_ext_cbs[_ext]; \
|
||||
static const struct can_mcan_callbacks _name = { \
|
||||
.tx = _name##_tx_cbs, \
|
||||
.std = _name##_std_cbs, \
|
||||
.ext = _name##_ext_cbs, \
|
||||
.num_tx = _tx, \
|
||||
.num_std = _std, \
|
||||
.num_ext = _ext, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Define Bosch M_CAN TX and RX callbacks
|
||||
* @param node_id node identifier
|
||||
* @param _name callbacks variable name
|
||||
* @see CAN_MCAN_CALLBACKS_DEFINE()
|
||||
*/
|
||||
#define CAN_MCAN_DT_CALLBACKS_DEFINE(node_id, _name) \
|
||||
CAN_MCAN_CALLBACKS_DEFINE(_name, CAN_MCAN_DT_MRAM_TX_BUFFER_ELEMENTS(node_id), \
|
||||
CAN_MCAN_DT_MRAM_STD_FILTER_ELEMENTS(node_id), \
|
||||
CAN_MCAN_DT_MRAM_EXT_FILTER_ELEMENTS(node_id))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_CALLBACKS_DEFINE(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @param _name callbacks variable name
|
||||
* @see CAN_MCAN_DT_CALLBACKS_DEFINE()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_CALLBACKS_DEFINE(inst, _name) \
|
||||
CAN_MCAN_DT_CALLBACKS_DEFINE(DT_DRV_INST(inst), _name)
|
||||
|
||||
struct can_mcan_config {
|
||||
struct can_mcan_ops *ops;
|
||||
const struct can_mcan_ops *ops;
|
||||
const struct can_mcan_callbacks *callbacks;
|
||||
uint16_t mram_elements[CAN_MCAN_MRAM_CFG_NUM_CELLS];
|
||||
uint16_t mram_offsets[CAN_MCAN_MRAM_CFG_NUM_CELLS];
|
||||
size_t mram_size;
|
||||
uint32_t bus_speed;
|
||||
uint16_t sjw;
|
||||
uint16_t sample_point;
|
||||
|
@ -834,17 +1133,62 @@ struct can_mcan_config {
|
|||
const void *custom;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get an array containing the number of elements in Bosch M_CAN Message RAM
|
||||
*
|
||||
* The order of the array entries is given by the @ref CAN_MCAN_MRAM_CFG definitions.
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @return array of number of elements
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_ELEMENTS_GET(node_id) \
|
||||
{ \
|
||||
0, /* offset cell */ \
|
||||
CAN_MCAN_DT_MRAM_STD_FILTER_ELEMENTS(node_id), \
|
||||
CAN_MCAN_DT_MRAM_EXT_FILTER_ELEMENTS(node_id), \
|
||||
CAN_MCAN_DT_MRAM_RX_FIFO0_ELEMENTS(node_id), \
|
||||
CAN_MCAN_DT_MRAM_RX_FIFO1_ELEMENTS(node_id), \
|
||||
CAN_MCAN_DT_MRAM_RX_BUFFER_ELEMENTS(node_id), \
|
||||
CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEMENTS(node_id), \
|
||||
CAN_MCAN_DT_MRAM_TX_BUFFER_ELEMENTS(node_id) \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get an array containing the base offsets for element in Bosch M_CAN Message RAM
|
||||
*
|
||||
* The order of the array entries is given by the @ref CAN_MCAN_MRAM_CFG definitions.
|
||||
*
|
||||
* @param node_id node identifier
|
||||
* @return array of base offsets for elements
|
||||
*/
|
||||
#define CAN_MCAN_DT_MRAM_OFFSETS_GET(node_id) \
|
||||
{ \
|
||||
0, /* offset cell */ \
|
||||
CAN_MCAN_DT_MRAM_STD_FILTER_OFFSET(node_id), \
|
||||
CAN_MCAN_DT_MRAM_EXT_FILTER_OFFSET(node_id), \
|
||||
CAN_MCAN_DT_MRAM_RX_FIFO0_OFFSET(node_id), \
|
||||
CAN_MCAN_DT_MRAM_RX_FIFO1_OFFSET(node_id), \
|
||||
CAN_MCAN_DT_MRAM_RX_BUFFER_OFFSET(node_id), \
|
||||
CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_OFFSET(node_id), \
|
||||
CAN_MCAN_DT_MRAM_TX_BUFFER_OFFSET(node_id) \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Static initializer for @p can_mcan_config struct
|
||||
*
|
||||
* @param node_id Devicetree node identifier
|
||||
* @param _custom Pointer to custom driver frontend configuration structure
|
||||
* @param _ops Pointer to front-end @a can_mcan_ops
|
||||
* @param _cbs Pointer to front-end @a can_mcan_callbacks
|
||||
*/
|
||||
#ifdef CONFIG_CAN_FD_MODE
|
||||
#define CAN_MCAN_DT_CONFIG_GET(node_id, _custom, _ops) \
|
||||
#define CAN_MCAN_DT_CONFIG_GET(node_id, _custom, _ops, _cbs) \
|
||||
{ \
|
||||
.ops = _ops, \
|
||||
.callbacks = _cbs, \
|
||||
.mram_elements = CAN_MCAN_DT_MRAM_ELEMENTS_GET(node_id), \
|
||||
.mram_offsets = CAN_MCAN_DT_MRAM_OFFSETS_GET(node_id), \
|
||||
.mram_size = CAN_MCAN_DT_MRAM_ELEMENTS_SIZE(node_id), \
|
||||
.bus_speed = DT_PROP(node_id, bus_speed), \
|
||||
.sjw = DT_PROP(node_id, sjw), \
|
||||
.sample_point = DT_PROP_OR(node_id, sample_point, 0), \
|
||||
|
@ -862,9 +1206,13 @@ struct can_mcan_config {
|
|||
.custom = _custom, \
|
||||
}
|
||||
#else /* CONFIG_CAN_FD_MODE */
|
||||
#define CAN_MCAN_DT_CONFIG_GET(node_id, _custom, _ops) \
|
||||
#define CAN_MCAN_DT_CONFIG_GET(node_id, _custom, _ops, _cbs) \
|
||||
{ \
|
||||
.ops = _ops, \
|
||||
.callbacks = _cbs, \
|
||||
.mram_elements = CAN_MCAN_DT_MRAM_ELEMENTS_GET(node_id), \
|
||||
.mram_offsets = CAN_MCAN_DT_MRAM_OFFSETS_GET(node_id), \
|
||||
.mram_size = CAN_MCAN_DT_MRAM_ELEMENTS_SIZE(node_id), \
|
||||
.bus_speed = DT_PROP(node_id, bus_speed), \
|
||||
.sjw = DT_PROP(node_id, sjw), \
|
||||
.sample_point = DT_PROP_OR(node_id, sample_point, 0), \
|
||||
|
@ -882,14 +1230,14 @@ struct can_mcan_config {
|
|||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @param _custom Pointer to custom driver frontend configuration structure
|
||||
* @param _ops Pointer to front-end @a can_mcan_ops
|
||||
* @param _cbs Pointer to front-end @a can_mcan_callbacks
|
||||
* @see CAN_MCAN_DT_CONFIG_GET()
|
||||
*/
|
||||
#define CAN_MCAN_DT_CONFIG_INST_GET(inst, _custom, _ops) \
|
||||
CAN_MCAN_DT_CONFIG_GET(DT_DRV_INST(inst), _custom, _ops)
|
||||
#define CAN_MCAN_DT_CONFIG_INST_GET(inst, _custom, _ops, _cbs) \
|
||||
CAN_MCAN_DT_CONFIG_GET(DT_DRV_INST(inst), _custom, _ops, _cbs)
|
||||
|
||||
/**
|
||||
* @brief Initializer for a @a can_mcan_data struct
|
||||
* @param _msg_ram Pointer to message RAM structure
|
||||
* @param _custom Pointer to custom driver frontend data structure
|
||||
*/
|
||||
#define CAN_MCAN_DATA_INITIALIZER(_custom) \
|
||||
|
|
|
@ -23,16 +23,13 @@ LOG_MODULE_REGISTER(can_mcux_mcan, CONFIG_CAN_LOG_LEVEL);
|
|||
|
||||
struct mcux_mcan_config {
|
||||
mm_reg_t base;
|
||||
mem_addr_t mram;
|
||||
const struct device *clock_dev;
|
||||
clock_control_subsys_t clock_subsys;
|
||||
void (*irq_config_func)(const struct device *dev);
|
||||
const struct pinctrl_dev_config *pincfg;
|
||||
};
|
||||
|
||||
struct mcux_mcan_data {
|
||||
struct can_mcan_msg_sram msg_ram __nocache;
|
||||
};
|
||||
|
||||
static int mcux_mcan_read_reg(const struct device *dev, uint16_t reg, uint32_t *val)
|
||||
{
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
|
@ -51,27 +48,27 @@ static int mcux_mcan_write_reg(const struct device *dev, uint16_t reg, uint32_t
|
|||
|
||||
static int mcux_mcan_read_mram(const struct device *dev, uint16_t offset, void *dst, size_t len)
|
||||
{
|
||||
struct can_mcan_data *mcan_data = dev->data;
|
||||
struct mcux_mcan_data *mcux_data = mcan_data->custom;
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
const struct mcux_mcan_config *mcux_config = mcan_config->custom;
|
||||
|
||||
return can_mcan_sys_read_mram(POINTER_TO_UINT(&mcux_data->msg_ram), offset, dst, len);
|
||||
return can_mcan_sys_read_mram(mcux_config->mram, offset, dst, len);
|
||||
}
|
||||
|
||||
static int mcux_mcan_write_mram(const struct device *dev, uint16_t offset, const void *src,
|
||||
size_t len)
|
||||
{
|
||||
struct can_mcan_data *mcan_data = dev->data;
|
||||
struct mcux_mcan_data *mcux_data = mcan_data->custom;
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
const struct mcux_mcan_config *mcux_config = mcan_config->custom;
|
||||
|
||||
return can_mcan_sys_write_mram(POINTER_TO_UINT(&mcux_data->msg_ram), offset, src, len);
|
||||
return can_mcan_sys_write_mram(mcux_config->mram, offset, src, len);
|
||||
}
|
||||
|
||||
static int mcux_mcan_clear_mram(const struct device *dev, uint16_t offset, size_t len)
|
||||
{
|
||||
struct can_mcan_data *mcan_data = dev->data;
|
||||
struct mcux_mcan_data *mcux_data = mcan_data->custom;
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
const struct mcux_mcan_config *mcux_config = mcan_config->custom;
|
||||
|
||||
return can_mcan_sys_clear_mram(POINTER_TO_UINT(&mcux_data->msg_ram), offset, len);
|
||||
return can_mcan_sys_clear_mram(mcux_config->mram, offset, len);
|
||||
}
|
||||
|
||||
static int mcux_mcan_get_core_clock(const struct device *dev, uint32_t *rate)
|
||||
|
@ -87,9 +84,7 @@ static int mcux_mcan_init(const struct device *dev)
|
|||
{
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
const struct mcux_mcan_config *mcux_config = mcan_config->custom;
|
||||
struct can_mcan_data *mcan_data = dev->data;
|
||||
struct mcux_mcan_data *mcux_data = mcan_data->custom;
|
||||
const uintptr_t mrba = POINTER_TO_UINT(&mcux_data->msg_ram) & MCUX_MCAN_MRBA_BA;
|
||||
const uintptr_t mrba = mcux_config->mram & MCUX_MCAN_MRBA_BA;
|
||||
int err;
|
||||
|
||||
if (!device_is_ready(mcux_config->clock_dev)) {
|
||||
|
@ -113,7 +108,7 @@ static int mcux_mcan_init(const struct device *dev)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
err = can_mcan_configure_mram(dev, mrba, POINTER_TO_UINT(&mcux_data->msg_ram));
|
||||
err = can_mcan_configure_mram(dev, mrba, mcux_config->mram);
|
||||
if (err != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -204,12 +199,17 @@ static const struct can_mcan_ops mcux_mcan_ops = {
|
|||
};
|
||||
|
||||
#define MCUX_MCAN_INIT(n) \
|
||||
CAN_MCAN_DT_INST_BUILD_ASSERT_MRAM_CFG(n); \
|
||||
PINCTRL_DT_INST_DEFINE(n); \
|
||||
\
|
||||
static void mcux_mcan_irq_config_##n(const struct device *dev); \
|
||||
\
|
||||
CAN_MCAN_DT_INST_CALLBACKS_DEFINE(n, mcux_mcan_cbs_##n); \
|
||||
CAN_MCAN_DT_INST_MRAM_DEFINE(n, mcux_mcan_mram_##n); \
|
||||
\
|
||||
static const struct mcux_mcan_config mcux_mcan_config_##n = { \
|
||||
.base = (mm_reg_t)DT_INST_REG_ADDR(n), \
|
||||
.base = CAN_MCAN_DT_INST_MCAN_ADDR(n), \
|
||||
.mram = (mem_addr_t)POINTER_TO_UINT(&mcux_mcan_mram_##n), \
|
||||
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
|
||||
.clock_subsys = (clock_control_subsys_t) \
|
||||
DT_INST_CLOCKS_CELL(n, name), \
|
||||
|
@ -219,12 +219,11 @@ static const struct can_mcan_ops mcux_mcan_ops = {
|
|||
\
|
||||
static const struct can_mcan_config can_mcan_config_##n = \
|
||||
CAN_MCAN_DT_CONFIG_INST_GET(n, &mcux_mcan_config_##n, \
|
||||
&mcux_mcan_ops); \
|
||||
\
|
||||
static struct mcux_mcan_data mcux_mcan_data_##n; \
|
||||
&mcux_mcan_ops, \
|
||||
&mcux_mcan_cbs_##n); \
|
||||
\
|
||||
static struct can_mcan_data can_mcan_data_##n = \
|
||||
CAN_MCAN_DATA_INITIALIZER(&mcux_mcan_data_##n); \
|
||||
CAN_MCAN_DATA_INITIALIZER(NULL); \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(n, &mcux_mcan_init, NULL, \
|
||||
&can_mcan_data_##n, \
|
||||
|
|
|
@ -21,16 +21,13 @@ LOG_MODULE_REGISTER(can_sam, CONFIG_CAN_LOG_LEVEL);
|
|||
|
||||
struct can_sam_config {
|
||||
mm_reg_t base;
|
||||
mem_addr_t mram;
|
||||
void (*config_irq)(void);
|
||||
const struct atmel_sam_pmc_config clock_cfg;
|
||||
const struct pinctrl_dev_config *pcfg;
|
||||
int divider;
|
||||
};
|
||||
|
||||
struct can_sam_data {
|
||||
struct can_mcan_msg_sram msg_ram;
|
||||
};
|
||||
|
||||
static int can_sam_read_reg(const struct device *dev, uint16_t reg, uint32_t *val)
|
||||
{
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
|
@ -49,27 +46,27 @@ static int can_sam_write_reg(const struct device *dev, uint16_t reg, uint32_t va
|
|||
|
||||
static int can_sam_read_mram(const struct device *dev, uint16_t offset, void *dst, size_t len)
|
||||
{
|
||||
struct can_mcan_data *mcan_data = dev->data;
|
||||
struct can_sam_data *sam_data = mcan_data->custom;
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
const struct can_sam_config *sam_config = mcan_config->custom;
|
||||
|
||||
return can_mcan_sys_read_mram(POINTER_TO_UINT(&sam_data->msg_ram), offset, dst, len);
|
||||
return can_mcan_sys_read_mram(sam_config->mram, offset, dst, len);
|
||||
}
|
||||
|
||||
static int can_sam_write_mram(const struct device *dev, uint16_t offset, const void *src,
|
||||
size_t len)
|
||||
{
|
||||
struct can_mcan_data *mcan_data = dev->data;
|
||||
struct can_sam_data *sam_data = mcan_data->custom;
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
const struct can_sam_config *sam_config = mcan_config->custom;
|
||||
|
||||
return can_mcan_sys_write_mram(POINTER_TO_UINT(&sam_data->msg_ram), offset, src, len);
|
||||
return can_mcan_sys_write_mram(sam_config->mram, offset, src, len);
|
||||
}
|
||||
|
||||
static int can_sam_clear_mram(const struct device *dev, uint16_t offset, size_t len)
|
||||
{
|
||||
struct can_mcan_data *mcan_data = dev->data;
|
||||
struct can_sam_data *sam_data = mcan_data->custom;
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
const struct can_sam_config *sam_config = mcan_config->custom;
|
||||
|
||||
return can_mcan_sys_clear_mram(POINTER_TO_UINT(&sam_data->msg_ram), offset, len);
|
||||
return can_mcan_sys_clear_mram(sam_config->mram, offset, len);
|
||||
}
|
||||
|
||||
static int can_sam_get_core_clock(const struct device *dev, uint32_t *rate)
|
||||
|
@ -96,8 +93,6 @@ static int can_sam_init(const struct device *dev)
|
|||
{
|
||||
const struct can_mcan_config *mcan_cfg = dev->config;
|
||||
const struct can_sam_config *sam_cfg = mcan_cfg->custom;
|
||||
struct can_mcan_data *mcan_data = dev->data;
|
||||
struct can_sam_data *sam_data = mcan_data->custom;
|
||||
int ret;
|
||||
|
||||
can_sam_clock_enable(sam_cfg);
|
||||
|
@ -107,7 +102,7 @@ static int can_sam_init(const struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = can_mcan_configure_mram(dev, 0U, POINTER_TO_UINT(&sam_data->msg_ram));
|
||||
ret = can_mcan_configure_mram(dev, 0U, sam_cfg->mram);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -195,8 +190,12 @@ static void config_can_##inst##_irq(void)
|
|||
}
|
||||
|
||||
#define CAN_SAM_CFG_INST(inst) \
|
||||
CAN_MCAN_DT_INST_CALLBACKS_DEFINE(inst, can_sam_cbs_##inst); \
|
||||
CAN_MCAN_DT_INST_MRAM_DEFINE(inst, can_sam_mram_##inst); \
|
||||
\
|
||||
static const struct can_sam_config can_sam_cfg_##inst = { \
|
||||
.base = (mm_reg_t)DT_INST_REG_ADDR(inst), \
|
||||
.base = CAN_MCAN_DT_INST_MCAN_ADDR(inst), \
|
||||
.mram = (mem_addr_t)POINTER_TO_UINT(&can_sam_mram_##inst), \
|
||||
.clock_cfg = SAM_DT_INST_CLOCK_PMC_CFG(inst), \
|
||||
.divider = DT_INST_PROP(inst, divider), \
|
||||
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
|
||||
|
@ -205,13 +204,12 @@ static void config_can_##inst##_irq(void)
|
|||
\
|
||||
static const struct can_mcan_config can_mcan_cfg_##inst = \
|
||||
CAN_MCAN_DT_CONFIG_INST_GET(inst, &can_sam_cfg_##inst, \
|
||||
&can_sam_ops);
|
||||
&can_sam_ops, \
|
||||
&can_sam_cbs_##inst);
|
||||
|
||||
#define CAN_SAM_DATA_INST(inst) \
|
||||
static struct can_sam_data can_sam_data_##inst; \
|
||||
\
|
||||
static struct can_mcan_data can_mcan_data_##inst = \
|
||||
CAN_MCAN_DATA_INITIALIZER(&can_sam_data_##inst);
|
||||
CAN_MCAN_DATA_INITIALIZER(NULL);
|
||||
|
||||
#define CAN_SAM_DEVICE_INST(inst) \
|
||||
DEVICE_DT_INST_DEFINE(inst, &can_sam_init, NULL, \
|
||||
|
@ -221,6 +219,7 @@ static void config_can_##inst##_irq(void)
|
|||
&can_sam_driver_api);
|
||||
|
||||
#define CAN_SAM_INST(inst) \
|
||||
CAN_MCAN_DT_INST_BUILD_ASSERT_MRAM_CFG(inst); \
|
||||
PINCTRL_DT_INST_DEFINE(inst); \
|
||||
CAN_SAM_IRQ_CFG_FUNCTION(inst) \
|
||||
CAN_SAM_CFG_INST(inst) \
|
||||
|
|
|
@ -21,6 +21,7 @@ LOG_MODULE_REGISTER(can_sam0, CONFIG_CAN_LOG_LEVEL);
|
|||
|
||||
struct can_sam0_config {
|
||||
mm_reg_t base;
|
||||
mem_addr_t mram;
|
||||
void (*config_irq)(void);
|
||||
const struct pinctrl_dev_config *pcfg;
|
||||
volatile uint32_t *mclk;
|
||||
|
@ -29,10 +30,6 @@ struct can_sam0_config {
|
|||
int divider;
|
||||
};
|
||||
|
||||
struct can_sam0_data {
|
||||
struct can_mcan_msg_sram msg_ram;
|
||||
};
|
||||
|
||||
static int can_sam0_read_reg(const struct device *dev, uint16_t reg, uint32_t *val)
|
||||
{
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
|
@ -65,27 +62,27 @@ static int can_sam0_write_reg(const struct device *dev, uint16_t reg, uint32_t v
|
|||
|
||||
static int can_sam0_read_mram(const struct device *dev, uint16_t offset, void *dst, size_t len)
|
||||
{
|
||||
struct can_mcan_data *mcan_data = dev->data;
|
||||
struct can_sam0_data *sam_data = mcan_data->custom;
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
const struct can_sam0_config *sam_config = mcan_config->custom;
|
||||
|
||||
return can_mcan_sys_read_mram(POINTER_TO_UINT(&sam_data->msg_ram), offset, dst, len);
|
||||
return can_mcan_sys_read_mram(sam_config->mram, offset, dst, len);
|
||||
}
|
||||
|
||||
static int can_sam0_write_mram(const struct device *dev, uint16_t offset, const void *src,
|
||||
size_t len)
|
||||
{
|
||||
struct can_mcan_data *mcan_data = dev->data;
|
||||
struct can_sam0_data *sam_data = mcan_data->custom;
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
const struct can_sam0_config *sam_config = mcan_config->custom;
|
||||
|
||||
return can_mcan_sys_write_mram(POINTER_TO_UINT(&sam_data->msg_ram), offset, src, len);
|
||||
return can_mcan_sys_write_mram(sam_config->mram, offset, src, len);
|
||||
}
|
||||
|
||||
static int can_sam0_clear_mram(const struct device *dev, uint16_t offset, size_t len)
|
||||
{
|
||||
struct can_mcan_data *mcan_data = dev->data;
|
||||
struct can_sam0_data *sam_data = mcan_data->custom;
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
const struct can_sam0_config *sam_config = mcan_config->custom;
|
||||
|
||||
return can_mcan_sys_clear_mram(POINTER_TO_UINT(&sam_data->msg_ram), offset, len);
|
||||
return can_mcan_sys_clear_mram(sam_config->mram, offset, len);
|
||||
}
|
||||
|
||||
void can_sam0_line_x_isr(const struct device *dev)
|
||||
|
@ -123,8 +120,6 @@ static int can_sam0_init(const struct device *dev)
|
|||
{
|
||||
const struct can_mcan_config *mcan_cfg = dev->config;
|
||||
const struct can_sam0_config *sam_cfg = mcan_cfg->custom;
|
||||
struct can_mcan_data *mcan_data = dev->data;
|
||||
struct can_sam0_data *sam_data = mcan_data->custom;
|
||||
int ret;
|
||||
|
||||
can_sam0_clock_enable(sam_cfg);
|
||||
|
@ -135,7 +130,7 @@ static int can_sam0_init(const struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = can_mcan_configure_mram(dev, 0U, POINTER_TO_UINT(&sam_data->msg_ram));
|
||||
ret = can_mcan_configure_mram(dev, 0U, sam_cfg->mram);
|
||||
if (ret != 0) {
|
||||
LOG_ERR("failed to configure message ram");
|
||||
return ret;
|
||||
|
@ -221,8 +216,12 @@ static void config_can_##inst##_irq(void) \
|
|||
}
|
||||
|
||||
#define CAN_SAM0_CFG_INST(inst) \
|
||||
CAN_MCAN_DT_INST_CALLBACKS_DEFINE(inst, can_sam0_cbs_##inst); \
|
||||
CAN_MCAN_DT_INST_MRAM_DEFINE(inst, can_sam0_mram_##inst); \
|
||||
\
|
||||
static const struct can_sam0_config can_sam0_cfg_##inst = { \
|
||||
.base = (mm_reg_t)DT_INST_REG_ADDR(inst), \
|
||||
.base = CAN_MCAN_DT_INST_MCAN_ADDR(inst), \
|
||||
.mram = (mem_addr_t)POINTER_TO_UINT(&can_sam0_mram_##inst), \
|
||||
.mclk = (volatile uint32_t *)MCLK_MASK_DT_INT_REG_ADDR(inst), \
|
||||
.mclk_mask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(inst, mclk, bit)), \
|
||||
.gclk_core_id = DT_INST_CLOCKS_CELL_BY_NAME(inst, gclk, periph_ch), \
|
||||
|
@ -232,13 +231,12 @@ static void config_can_##inst##_irq(void) \
|
|||
}; \
|
||||
\
|
||||
static const struct can_mcan_config can_mcan_cfg_##inst = \
|
||||
CAN_MCAN_DT_CONFIG_INST_GET(inst, &can_sam0_cfg_##inst, &can_sam0_ops);
|
||||
CAN_MCAN_DT_CONFIG_INST_GET(inst, &can_sam0_cfg_##inst, &can_sam0_ops, \
|
||||
&can_sam0_cbs_##inst);
|
||||
|
||||
#define CAN_SAM0_DATA_INST(inst) \
|
||||
static struct can_sam0_data can_sam0_data_##inst; \
|
||||
\
|
||||
static struct can_mcan_data can_mcan_data_##inst = \
|
||||
CAN_MCAN_DATA_INITIALIZER(&can_sam0_data_##inst);
|
||||
CAN_MCAN_DATA_INITIALIZER(NULL);
|
||||
|
||||
#define CAN_SAM0_DEVICE_INST(inst) \
|
||||
DEVICE_DT_INST_DEFINE(inst, &can_sam0_init, NULL, \
|
||||
|
@ -248,6 +246,7 @@ static void config_can_##inst##_irq(void) \
|
|||
&can_sam0_driver_api);
|
||||
|
||||
#define CAN_SAM0_INST(inst) \
|
||||
CAN_MCAN_DT_INST_BUILD_ASSERT_MRAM_CFG(inst); \
|
||||
PINCTRL_DT_INST_DEFINE(inst); \
|
||||
CAN_SAM0_IRQ_CFG_FUNCTION(inst) \
|
||||
CAN_SAM0_CFG_INST(inst) \
|
||||
|
|
|
@ -635,14 +635,21 @@ static const struct can_mcan_ops can_stm32fd_ops = {
|
|||
.clear_mram = can_stm32fd_clear_mram,
|
||||
};
|
||||
|
||||
/* Assert that the Message RAM configuration matches the fixed hardware configuration */
|
||||
BUILD_ASSERT(NUM_STD_FILTER_ELEMENTS == 28, "Standard filter elements must be 28");
|
||||
BUILD_ASSERT(NUM_EXT_FILTER_ELEMENTS == 8, "Extended filter elements must be 8");
|
||||
BUILD_ASSERT(NUM_RX_FIFO0_ELEMENTS == 3, "Rx FIFO 0 elements must be 3");
|
||||
BUILD_ASSERT(NUM_RX_FIFO1_ELEMENTS == 3, "Rx FIFO 1 elements must be 3");
|
||||
BUILD_ASSERT(NUM_RX_BUF_ELEMENTS == 0, "Rx Buffer elements must be 0");
|
||||
BUILD_ASSERT(NUM_TX_EVENT_FIFO_ELEMENTS == 3, "Tx Event FIFO elements must be 3");
|
||||
BUILD_ASSERT(NUM_TX_BUF_ELEMENTS == 3, "Tx Buffer elements must be 0");
|
||||
#define CAN_STM32FD_BUILD_ASSERT_MRAM_CFG(inst) \
|
||||
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_STD_FILTER_ELEMENTS(inst) == 28, \
|
||||
"Standard filter elements must be 28"); \
|
||||
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_EXT_FILTER_ELEMENTS(inst) == 8, \
|
||||
"Extended filter elements must be 8"); \
|
||||
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_RX_FIFO0_ELEMENTS(inst) == 3, \
|
||||
"Rx FIFO 0 elements must be 3"); \
|
||||
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_RX_FIFO1_ELEMENTS(inst) == 3, \
|
||||
"Rx FIFO 1 elements must be 3"); \
|
||||
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_RX_BUFFER_ELEMENTS(inst) == 0, \
|
||||
"Rx Buffer elements must be 0"); \
|
||||
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_TX_EVENT_FIFO_ELEMENTS(inst) == 3, \
|
||||
"Tx Event FIFO elements must be 3"); \
|
||||
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_TX_BUFFER_ELEMENTS(inst) == 3, \
|
||||
"Tx Buffer elements must be 0");
|
||||
|
||||
#define CAN_STM32FD_IRQ_CFG_FUNCTION(inst) \
|
||||
static void config_can_##inst##_irq(void) \
|
||||
|
@ -659,13 +666,22 @@ static void config_can_##inst##_irq(void) \
|
|||
}
|
||||
|
||||
#define CAN_STM32FD_CFG_INST(inst) \
|
||||
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_ELEMENTS_SIZE(inst) <= \
|
||||
CAN_MCAN_DT_INST_MRAM_SIZE(inst), \
|
||||
"Insufficient Message RAM size to hold elements"); \
|
||||
\
|
||||
PINCTRL_DT_INST_DEFINE(inst); \
|
||||
CAN_MCAN_CALLBACKS_DEFINE(can_stm32fd_cbs_##inst, \
|
||||
CAN_MCAN_DT_INST_MRAM_TX_BUFFER_ELEMENTS(inst), \
|
||||
CONFIG_CAN_MAX_STD_ID_FILTER, \
|
||||
CONFIG_CAN_MAX_EXT_ID_FILTER); \
|
||||
\
|
||||
static const struct stm32_pclken can_stm32fd_pclken_##inst[] = \
|
||||
STM32_DT_INST_CLOCKS(inst); \
|
||||
\
|
||||
static const struct can_stm32fd_config can_stm32fd_cfg_##inst = { \
|
||||
.base = (mm_reg_t)DT_INST_REG_ADDR_BY_NAME(inst, m_can), \
|
||||
.mram = (mem_addr_t)DT_INST_REG_ADDR_BY_NAME(inst, message_ram), \
|
||||
.base = CAN_MCAN_DT_INST_MCAN_ADDR(inst), \
|
||||
.mram = CAN_MCAN_DT_INST_MRAM_ADDR(inst), \
|
||||
.pclken = can_stm32fd_pclken_##inst, \
|
||||
.pclk_len = DT_INST_NUM_CLOCKS(inst), \
|
||||
.config_irq = config_can_##inst##_irq, \
|
||||
|
@ -675,7 +691,8 @@ static void config_can_##inst##_irq(void) \
|
|||
\
|
||||
static const struct can_mcan_config can_mcan_cfg_##inst = \
|
||||
CAN_MCAN_DT_CONFIG_INST_GET(inst, &can_stm32fd_cfg_##inst, \
|
||||
&can_stm32fd_ops);
|
||||
&can_stm32fd_ops, \
|
||||
&can_stm32fd_cbs_##inst);
|
||||
|
||||
#define CAN_STM32FD_DATA_INST(inst) \
|
||||
static struct can_mcan_data can_mcan_data_##inst = \
|
||||
|
@ -687,10 +704,11 @@ static void config_can_##inst##_irq(void) \
|
|||
POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \
|
||||
&can_stm32fd_driver_api);
|
||||
|
||||
#define CAN_STM32FD_INST(inst) \
|
||||
CAN_STM32FD_IRQ_CFG_FUNCTION(inst) \
|
||||
CAN_STM32FD_CFG_INST(inst) \
|
||||
CAN_STM32FD_DATA_INST(inst) \
|
||||
#define CAN_STM32FD_INST(inst) \
|
||||
CAN_STM32FD_BUILD_ASSERT_MRAM_CFG(inst) \
|
||||
CAN_STM32FD_IRQ_CFG_FUNCTION(inst) \
|
||||
CAN_STM32FD_CFG_INST(inst) \
|
||||
CAN_STM32FD_DATA_INST(inst) \
|
||||
CAN_STM32FD_DEVICE_INST(inst)
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(CAN_STM32FD_INST)
|
||||
|
|
|
@ -215,13 +215,19 @@ static const struct can_mcan_ops can_stm32h7_ops = {
|
|||
};
|
||||
|
||||
#define CAN_STM32H7_MCAN_INIT(n) \
|
||||
CAN_MCAN_DT_INST_BUILD_ASSERT_MRAM_CFG(n); \
|
||||
BUILD_ASSERT(CAN_MCAN_DT_INST_MRAM_ELEMENTS_SIZE(n) <= \
|
||||
CAN_MCAN_DT_INST_MRAM_SIZE(n), \
|
||||
"Insufficient Message RAM size to hold elements"); \
|
||||
\
|
||||
static void stm32h7_mcan_irq_config_##n(void); \
|
||||
\
|
||||
PINCTRL_DT_INST_DEFINE(n); \
|
||||
CAN_MCAN_DT_INST_CALLBACKS_DEFINE(n, can_stm32h7_cbs_##n); \
|
||||
\
|
||||
static const struct can_stm32h7_config can_stm32h7_cfg_##n = { \
|
||||
.base = (mm_reg_t)DT_INST_REG_ADDR_BY_NAME(n, m_can), \
|
||||
.mram = (mem_addr_t)DT_INST_REG_ADDR_BY_NAME(n, message_ram), \
|
||||
.base = CAN_MCAN_DT_INST_MCAN_ADDR(n), \
|
||||
.mram = CAN_MCAN_DT_INST_MRAM_ADDR(n), \
|
||||
.config_irq = stm32h7_mcan_irq_config_##n, \
|
||||
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
|
||||
.pclken = { \
|
||||
|
@ -232,7 +238,8 @@ static const struct can_mcan_ops can_stm32h7_ops = {
|
|||
\
|
||||
static const struct can_mcan_config can_mcan_cfg_##n = \
|
||||
CAN_MCAN_DT_CONFIG_INST_GET(n, &can_stm32h7_cfg_##n, \
|
||||
&can_stm32h7_ops); \
|
||||
&can_stm32h7_ops, \
|
||||
&can_stm32h7_cbs_##n); \
|
||||
\
|
||||
static struct can_mcan_data can_mcan_data_##n = \
|
||||
CAN_MCAN_DATA_INITIALIZER(NULL); \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue