From 0f36f1a3eeaace037e788445aa2e5101ec1f8809 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Mon, 22 May 2023 16:31:09 +0200 Subject: [PATCH] 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 --- drivers/can/can_mcan.c | 227 +++++----- drivers/can/can_mcan.h | 594 ++++++++++++++++++++----- drivers/can/can_mcux_mcan.c | 43 +- drivers/can/can_sam.c | 41 +- drivers/can/can_sam0.c | 41 +- drivers/can/can_stm32fd.c | 48 +- drivers/can/can_stm32h7.c | 13 +- dts/arm/atmel/samc21.dtsi | 61 ++- dts/arm/atmel/same70.dtsi | 57 ++- dts/arm/st/g0/stm32g0b1.dtsi | 30 +- dts/arm/st/g4/stm32g4.dtsi | 30 +- dts/arm/st/g4/stm32g473.dtsi | 27 +- dts/arm/st/g4/stm32g491.dtsi | 27 +- dts/arm/st/h5/stm32h5.dtsi | 30 +- dts/arm/st/h5/stm32h562.dtsi | 29 +- dts/arm/st/h7/stm32h7.dtsi | 57 ++- dts/arm/st/h7/stm32h723.dtsi | 27 +- dts/arm/st/u5/stm32u5.dtsi | 30 +- dts/bindings/can/atmel,sam-can.yaml | 2 +- dts/bindings/can/atmel,sam0-can.yaml | 2 +- dts/bindings/can/bosch,m_can-base.yaml | 2 +- dts/bindings/can/nxp,lpc-mcan.yaml | 2 +- dts/bindings/can/st,stm32-fdcan.yaml | 2 +- dts/bindings/can/st,stm32h7-fdcan.yaml | 2 +- 24 files changed, 878 insertions(+), 546 deletions(-) diff --git a/drivers/can/can_mcan.c b/drivers/can/can_mcan.c index 9a7e3fdd85a..f88d805b1f1 100644 --- a/drivers/can/can_mcan.c +++ b/drivers/can/can_mcan.c @@ -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); } diff --git a/drivers/can/can_mcan.h b/drivers/can/can_mcan.h index 98ccc793347..79c39c59908 100644 --- a/drivers/can/can_mcan.h +++ b/drivers/can/can_mcan.h @@ -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) \ diff --git a/drivers/can/can_mcux_mcan.c b/drivers/can/can_mcux_mcan.c index 0663c25e65e..32adb762fd3 100644 --- a/drivers/can/can_mcux_mcan.c +++ b/drivers/can/can_mcux_mcan.c @@ -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, \ diff --git a/drivers/can/can_sam.c b/drivers/can/can_sam.c index 350bb5e70b9..5d0e04f3951 100644 --- a/drivers/can/can_sam.c +++ b/drivers/can/can_sam.c @@ -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) \ diff --git a/drivers/can/can_sam0.c b/drivers/can/can_sam0.c index 829acd11f1b..d44f1c7231e 100644 --- a/drivers/can/can_sam0.c +++ b/drivers/can/can_sam0.c @@ -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) \ diff --git a/drivers/can/can_stm32fd.c b/drivers/can/can_stm32fd.c index 7b9f9e964bd..a29a82d460a 100644 --- a/drivers/can/can_stm32fd.c +++ b/drivers/can/can_stm32fd.c @@ -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) diff --git a/drivers/can/can_stm32h7.c b/drivers/can/can_stm32h7.c index cc85a7a596f..22e225fd057 100644 --- a/drivers/can/can_stm32h7.c +++ b/drivers/can/can_stm32h7.c @@ -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); \ diff --git a/dts/arm/atmel/samc21.dtsi b/dts/arm/atmel/samc21.dtsi index 4ca5ec4c334..63421dbdb63 100644 --- a/dts/arm/atmel/samc21.dtsi +++ b/dts/arm/atmel/samc21.dtsi @@ -44,41 +44,36 @@ status = "disabled"; }; - can { - compatible = "bosch,m_can-base"; - #address-cells = <1>; - #size-cells = <1>; + can0: can@42001c00 { + compatible = "atmel,sam0-can"; + reg = <0x42001c00 0x100>; + interrupts = <15 0>; + interrupt-names = "LINE_0"; + clocks = <&gclk 26>, <&mclk 0x10 8>; + clock-names = "GCLK", "MCLK"; bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; + divider = <12>; + sjw = <1>; + sample-point = <875>; + sjw-data = <1>; + sample-point-data = <875>; + status = "disabled"; + }; - can0: can@42001c00 { - compatible = "atmel,sam0-can"; - reg = <0x42001c00 0x100>; - interrupts = <15 0>; - interrupt-names = "LINE_0"; - clocks = <&gclk 26>, <&mclk 0x10 8>; - clock-names = "GCLK", "MCLK"; - divider = <12>; - sjw = <1>; - sample-point = <875>; - sjw-data = <1>; - sample-point-data = <875>; - status = "disabled"; - }; - - can1: can@42002000 { - compatible = "atmel,sam0-can"; - reg = <0x42002000 0x100>; - interrupts = <16 0>; - interrupt-names = "LINE_0"; - clocks = <&gclk 27>, <&mclk 0x10 9>; - clock-names = "GCLK", "MCLK"; - divider = <12>; - sjw = <1>; - sample-point = <875>; - sjw-data = <1>; - sample-point-data = <875>; - status = "disabled"; - }; + can1: can@42002000 { + compatible = "atmel,sam0-can"; + reg = <0x42002000 0x100>; + interrupts = <16 0>; + interrupt-names = "LINE_0"; + clocks = <&gclk 27>, <&mclk 0x10 9>; + clock-names = "GCLK", "MCLK"; + bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; + divider = <12>; + sjw = <1>; + sample-point = <875>; + sjw-data = <1>; + sample-point-data = <875>; + status = "disabled"; }; }; }; diff --git a/dts/arm/atmel/same70.dtsi b/dts/arm/atmel/same70.dtsi index 91cd3551356..804202af479 100644 --- a/dts/arm/atmel/same70.dtsi +++ b/dts/arm/atmel/same70.dtsi @@ -408,39 +408,34 @@ status = "disabled"; }; - can { - compatible = "bosch,m_can-base"; - #address-cells = <1>; - #size-cells = <1>; + can0: can@40030000 { + compatible = "atmel,sam-can"; + reg = <0x40030000 0x100>; + interrupts = <35 0>, <36 0>; + interrupt-names = "LINE_0", "LINE_1"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 35>; + divider = <6>; bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; + sjw = <1>; + sample-point = <875>; + sjw-data = <1>; + sample-point-data = <875>; + status = "disabled"; + }; - can0: can@40030000 { - compatible = "atmel,sam-can"; - reg = <0x40030000 0x100>; - interrupts = <35 0>, <36 0>; - interrupt-names = "LINE_0", "LINE_1"; - clocks = <&pmc PMC_TYPE_PERIPHERAL 35>; - divider = <6>; - sjw = <1>; - sample-point = <875>; - sjw-data = <1>; - sample-point-data = <875>; - status = "disabled"; - }; - - can1: can@40034000 { - compatible = "atmel,sam-can"; - reg = <0x40034000 0x100>; - interrupts = <37 0>, <38 0>; - interrupt-names = "LINE_0", "LINE_1"; - clocks = <&pmc PMC_TYPE_PERIPHERAL 37>; - divider = <6>; - sjw = <1>; - sample-point = <875>; - sjw-data = <1>; - sample-point-data = <875>; - status = "disabled"; - }; + can1: can@40034000 { + compatible = "atmel,sam-can"; + reg = <0x40034000 0x100>; + interrupts = <37 0>, <38 0>; + interrupt-names = "LINE_0", "LINE_1"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 37>; + divider = <6>; + bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; + sjw = <1>; + sample-point = <875>; + sjw-data = <1>; + sample-point-data = <875>; + status = "disabled"; }; rstc: rstc@400e1800 { diff --git a/dts/arm/st/g0/stm32g0b1.dtsi b/dts/arm/st/g0/stm32g0b1.dtsi index c3eba030e99..676b35e48e5 100644 --- a/dts/arm/st/g0/stm32g0b1.dtsi +++ b/dts/arm/st/g0/stm32g0b1.dtsi @@ -30,25 +30,19 @@ }; }; - can { - compatible = "bosch,m_can-base"; - #address-cells = <1>; - #size-cells = <1>; + can1: can@40006400 { + compatible = "st,stm32-fdcan"; + reg = <0x40006400 0x400>, <0x4000b400 0x350>; + reg-names = "m_can", "message_ram"; + interrupts = <21 0>, <22 0>; + interrupt-names = "LINE_0", "LINE_1"; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00001000>; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>; - - can1: can@40006400 { - compatible = "st,stm32-fdcan"; - reg = <0x40006400 0x400>, <0x4000B400 0x350>; - reg-names = "m_can", "message_ram"; - interrupts = <21 0>, <22 0>; - interrupt-names = "LINE_0", "LINE_1"; - clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00001000>; - status = "disabled"; - sjw = <1>; - sample-point = <875>; - sjw-data = <1>; - sample-point-data = <875>; - }; + sjw = <1>; + sample-point = <875>; + sjw-data = <1>; + sample-point-data = <875>; + status = "disabled"; }; usart5: serial@40005000 { diff --git a/dts/arm/st/g4/stm32g4.dtsi b/dts/arm/st/g4/stm32g4.dtsi index ef546926d7d..f08b4c2c012 100644 --- a/dts/arm/st/g4/stm32g4.dtsi +++ b/dts/arm/st/g4/stm32g4.dtsi @@ -381,25 +381,19 @@ status = "disabled"; }; - can { - compatible = "bosch,m_can-base"; - #address-cells = <1>; - #size-cells = <1>; + can1: can@40006400 { + compatible = "st,stm32-fdcan"; + reg = <0x40006400 0x400>, <0x4000a400 0x350>; + reg-names = "m_can", "message_ram"; + interrupts = <21 0>, <22 0>; + interrupt-names = "LINE_0", "LINE_1"; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>; - - can1: can@40006400 { - compatible = "st,stm32-fdcan"; - reg = <0x40006400 0x400>, <0x4000A400 0x350>; - reg-names = "m_can", "message_ram"; - interrupts = <21 0>, <22 0>; - interrupt-names = "LINE_0", "LINE_1"; - clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; - status = "disabled"; - sjw = <1>; - sample-point = <875>; - sjw-data = <1>; - sample-point-data = <875>; - }; + sjw = <1>; + sample-point = <875>; + sjw-data = <1>; + sample-point-data = <875>; + status = "disabled"; }; lptim1: timers@40007c00 { diff --git a/dts/arm/st/g4/stm32g473.dtsi b/dts/arm/st/g4/stm32g473.dtsi index c6a831655a5..7398c541f9f 100644 --- a/dts/arm/st/g4/stm32g473.dtsi +++ b/dts/arm/st/g4/stm32g473.dtsi @@ -84,20 +84,19 @@ status = "disabled"; }; - can { - can3: can@40006C00 { - compatible = "st,stm32-fdcan"; - reg = <0x40006C00 0x400>, <0x4000AAA0 0x350>; - reg-names = "m_can", "message_ram"; - interrupts = <88 0>, <89 0>; - interrupt-names = "LINE_0", "LINE_1"; - clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; - status = "disabled"; - sjw = <1>; - sample-point = <875>; - sjw-data = <1>; - sample-point-data = <875>; - }; + can3: can@40006c00 { + compatible = "st,stm32-fdcan"; + reg = <0x40006c00 0x400>, <0x4000a400 0x9f0>; + reg-names = "m_can", "message_ram"; + interrupts = <88 0>, <89 0>; + interrupt-names = "LINE_0", "LINE_1"; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; + bosch,mram-cfg = <0x6a0 28 8 3 3 0 3 3>; + sjw = <1>; + sample-point = <875>; + sjw-data = <1>; + sample-point-data = <875>; + status = "disabled"; }; }; }; diff --git a/dts/arm/st/g4/stm32g491.dtsi b/dts/arm/st/g4/stm32g491.dtsi index 7f930dc039b..b01d91b5a59 100644 --- a/dts/arm/st/g4/stm32g491.dtsi +++ b/dts/arm/st/g4/stm32g491.dtsi @@ -10,20 +10,19 @@ soc { compatible = "st,stm32g491", "st,stm32g4", "simple-bus"; - can { - can2: can@40006800 { - compatible = "st,stm32-fdcan"; - reg = <0x40006800 0x400>, <0x4000A750 0x350>; - reg-names = "m_can", "message_ram"; - interrupts = <86 0>, <87 0>; - interrupt-names = "LINE_0", "LINE_1"; - clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; - status = "disabled"; - sjw = <1>; - sample-point = <875>; - sjw-data = <1>; - sample-point-data = <875>; - }; + can2: can@40006800 { + compatible = "st,stm32-fdcan"; + reg = <0x40006800 0x400>, <0x4000a400 0x6a0>; + reg-names = "m_can", "message_ram"; + interrupts = <86 0>, <87 0>; + interrupt-names = "LINE_0", "LINE_1"; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; + sjw = <1>; + bosch,mram-cfg = <0x350 28 8 3 3 0 3 3>; + sample-point = <875>; + sjw-data = <1>; + sample-point-data = <875>; + status = "disabled"; }; timers20: timers@40015000 { diff --git a/dts/arm/st/h5/stm32h5.dtsi b/dts/arm/st/h5/stm32h5.dtsi index 8c61042d7a2..2052ea10c5d 100644 --- a/dts/arm/st/h5/stm32h5.dtsi +++ b/dts/arm/st/h5/stm32h5.dtsi @@ -436,25 +436,19 @@ status = "disabled"; }; - can { - compatible = "bosch,m_can-base"; - #address-cells = <1>; - #size-cells = <1>; + can1: can@4000a400 { + compatible = "st,stm32-fdcan"; + reg = <0x4000a400 0x400>, <0x4000ac00 0x350>; + reg-names = "m_can", "message_ram"; + interrupts = <39 0>, <40 0>; + interrupt-names = "LINE_0", "LINE_1"; + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>; - - can1: can@4000a400 { - compatible = "st,stm32-fdcan"; - reg = <0x4000a400 0x400>, <0x4000ac00 0x350>; - reg-names = "m_can", "message_ram"; - interrupts = <39 0>, <40 0>; - interrupt-names = "LINE_0", "LINE_1"; - clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>; - status = "disabled"; - sjw = <1>; - sample-point = <875>; - sjw-data = <1>; - sample-point-data = <875>; - }; + sjw = <1>; + sample-point = <875>; + sjw-data = <1>; + sample-point-data = <875>; + status = "disabled"; }; rng: rng@420c0800 { diff --git a/dts/arm/st/h5/stm32h562.dtsi b/dts/arm/st/h5/stm32h562.dtsi index 0ce86baa251..b5e32fc7054 100644 --- a/dts/arm/st/h5/stm32h562.dtsi +++ b/dts/arm/st/h5/stm32h562.dtsi @@ -293,21 +293,20 @@ status = "disabled"; }; - can { - can2: can@4000a800 { - compatible = "st,stm32-fdcan"; - reg = <0x4000a800 0x400>, <0x4000af50 0x350>; - reg-names = "m_can", "message_ram"; - interrupts = <109 0>, <110 0>; - interrupt-names = "LINE_0", "LINE_1"; - /* common clock FDCAN 1 & 2 */ - clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>; - status = "disabled"; - sjw = <1>; - sample-point = <875>; - sjw-data = <1>; - sample-point-data = <875>; - }; + can2: can@4000a800 { + compatible = "st,stm32-fdcan"; + reg = <0x4000a800 0x400>, <0x4000ac00 0x6a0>; + reg-names = "m_can", "message_ram"; + interrupts = <109 0>, <110 0>; + interrupt-names = "LINE_0", "LINE_1"; + /* common clock FDCAN 1 & 2 */ + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>; + bosch,mram-cfg = <0x350 28 8 3 3 0 3 3>; + sjw = <1>; + sample-point = <875>; + sjw-data = <1>; + sample-point-data = <875>; + status = "disabled"; }; }; }; diff --git a/dts/arm/st/h7/stm32h7.dtsi b/dts/arm/st/h7/stm32h7.dtsi index 6fbea4aeb34..012460b885a 100644 --- a/dts/arm/st/h7/stm32h7.dtsi +++ b/dts/arm/st/h7/stm32h7.dtsi @@ -465,39 +465,34 @@ status = "disabled"; }; - can { - compatible = "bosch,m_can-base"; - #address-cells = <1>; - #size-cells = <1>; + can1: can@4000a000 { + compatible = "st,stm32h7-fdcan"; + reg = <0x4000a000 0x400>, <0x4000ac00 0x350>; + reg-names = "m_can", "message_ram"; + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>; + interrupts = <19 0>, <21 0>, <63 0>; + interrupt-names = "LINE_0", "LINE_1", "CALIB"; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>; + sjw = <1>; + sample-point = <875>; + sjw-data = <1>; + sample-point-data = <875>; + status = "disabled"; + }; - can1: can@4000a000 { - compatible = "st,stm32h7-fdcan"; - reg = <0x4000a000 0x400>, <0x4000ac00 0x350>; - reg-names = "m_can", "message_ram"; - clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>; - interrupts = <19 0>, <21 0>, <63 0>; - interrupt-names = "LINE_0", "LINE_1", "CALIB"; - status = "disabled"; - sjw = <1>; - sample-point = <875>; - sjw-data = <1>; - sample-point-data = <875>; - }; - - can2: can@4000a400 { - compatible = "st,stm32h7-fdcan"; - reg = <0x4000a400 0x400>, <0x4000ac00 0x350>; - reg-names = "m_can", "message_ram"; - clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>; - interrupts = <20 0>, <22 0>, <63 0>; - interrupt-names = "LINE_0", "LINE_1", "CALIB"; - status = "disabled"; - sjw = <1>; - sample-point = <875>; - sjw-data = <1>; - sample-point-data = <875>; - }; + can2: can@4000a400 { + compatible = "st,stm32h7-fdcan"; + reg = <0x4000a400 0x400>, <0x4000ac00 0x6a0>; + reg-names = "m_can", "message_ram"; + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>; + interrupts = <20 0>, <22 0>, <63 0>; + interrupt-names = "LINE_0", "LINE_1", "CALIB"; + bosch,mram-cfg = <0x350 28 8 3 3 0 3 3>; + sjw = <1>; + sample-point = <875>; + sjw-data = <1>; + sample-point-data = <875>; + status = "disabled"; }; timers1: timers@40010000 { diff --git a/dts/arm/st/h7/stm32h723.dtsi b/dts/arm/st/h7/stm32h723.dtsi index 910f5e08130..4a2f17c5003 100644 --- a/dts/arm/st/h7/stm32h723.dtsi +++ b/dts/arm/st/h7/stm32h723.dtsi @@ -117,20 +117,19 @@ status = "disabled"; }; - can { - can3: can@4000D400 { - compatible = "st,stm32h7-fdcan"; - reg = <0x4000D400 0x400>, <0x4000ac00 0x350>; - reg-names = "m_can", "message_ram"; - clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>; - interrupts = <159 0>, <160 0>, <63 0>; - interrupt-names = "LINE_0", "LINE_1", "CALIB"; - sjw = <1>; - sample-point = <875>; - sjw-data = <1>; - sample-point-data = <875>; - status = "disabled"; - }; + can3: can@4000d400 { + compatible = "st,stm32h7-fdcan"; + reg = <0x4000d400 0x400>, <0x4000ac00 0x9f0>; + reg-names = "m_can", "message_ram"; + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>; + interrupts = <159 0>, <160 0>, <63 0>; + interrupt-names = "LINE_0", "LINE_1", "CALIB"; + bosch,mram-cfg = <0x6a0 28 8 3 3 0 3 3>; + sjw = <1>; + sample-point = <875>; + sjw-data = <1>; + sample-point-data = <875>; + status = "disabled"; }; rtc@58004000 { diff --git a/dts/arm/st/u5/stm32u5.dtsi b/dts/arm/st/u5/stm32u5.dtsi index 8e4358160e4..343bc8ed4e2 100644 --- a/dts/arm/st/u5/stm32u5.dtsi +++ b/dts/arm/st/u5/stm32u5.dtsi @@ -770,25 +770,19 @@ num-sampling-time-common-channels = <2>; }; - can { - compatible = "bosch,m_can-base"; - #address-cells = <1>; - #size-cells = <1>; + can1: can@4000a400 { + compatible = "st,stm32-fdcan"; + reg = <0x4000a400 0x400>, <0x4000ac00 0x350>; + reg-names = "m_can", "message_ram"; + interrupts = <39 0>, <40 0>; + interrupt-names = "LINE_0", "LINE_1"; + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>; bosch,mram-cfg = <0x0 28 8 3 3 0 3 3>; - - can1: can@4000a400 { - compatible = "st,stm32-fdcan"; - reg = <0x4000a400 0x400>, <0x4000ac00 0x350>; - reg-names = "m_can", "message_ram"; - interrupts = <39 0>, <40 0>; - interrupt-names = "LINE_0", "LINE_1"; - clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>; - status = "disabled"; - sjw = <1>; - sample-point = <875>; - sjw-data = <1>; - sample-point-data = <875>; - }; + sjw = <1>; + sample-point = <875>; + sjw-data = <1>; + sample-point-data = <875>; + status = "disabled"; }; ucpd1: ucpd@4000dc00 { diff --git a/dts/bindings/can/atmel,sam-can.yaml b/dts/bindings/can/atmel,sam-can.yaml index 7f00f6d2325..0d0dc268f4c 100644 --- a/dts/bindings/can/atmel,sam-can.yaml +++ b/dts/bindings/can/atmel,sam-can.yaml @@ -3,7 +3,7 @@ description: Specialization of Bosch m_can CAN-FD controller for Atmel SAM compatible: "atmel,sam-can" include: - - name: can-fd-controller.yaml + - name: bosch,m_can-base.yaml - name: pinctrl-device.yaml properties: diff --git a/dts/bindings/can/atmel,sam0-can.yaml b/dts/bindings/can/atmel,sam0-can.yaml index a555d8bf485..0a70dfd9d5e 100644 --- a/dts/bindings/can/atmel,sam0-can.yaml +++ b/dts/bindings/can/atmel,sam0-can.yaml @@ -3,7 +3,7 @@ description: Specialization of Bosch m_can CAN-FD controller for Atmel SAM0 compatible: "atmel,sam0-can" include: - - name: can-fd-controller.yaml + - name: bosch,m_can-base.yaml - name: pinctrl-device.yaml properties: diff --git a/dts/bindings/can/bosch,m_can-base.yaml b/dts/bindings/can/bosch,m_can-base.yaml index 1fb5ab48f0d..1663cf82082 100644 --- a/dts/bindings/can/bosch,m_can-base.yaml +++ b/dts/bindings/can/bosch,m_can-base.yaml @@ -1,6 +1,6 @@ description: Bosch M_CAN CAN-FD controller base -compatible: "bosch,m_can-base" +include: [can-fd-controller.yaml] properties: bosch,mram-cfg: diff --git a/dts/bindings/can/nxp,lpc-mcan.yaml b/dts/bindings/can/nxp,lpc-mcan.yaml index d411ed6d001..65a06baea87 100644 --- a/dts/bindings/can/nxp,lpc-mcan.yaml +++ b/dts/bindings/can/nxp,lpc-mcan.yaml @@ -2,7 +2,7 @@ description: NXP LPC SoC series MCAN CAN-FD controller 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: reg: diff --git a/dts/bindings/can/st,stm32-fdcan.yaml b/dts/bindings/can/st,stm32-fdcan.yaml index a7558265d00..36a38d97ca3 100644 --- a/dts/bindings/can/st,stm32-fdcan.yaml +++ b/dts/bindings/can/st,stm32-fdcan.yaml @@ -2,7 +2,7 @@ description: ST STM32 FDCAN CAN-FD controller compatible: "st,stm32-fdcan" -include: ["can-fd-controller.yaml", "pinctrl-device.yaml"] +include: ["bosch,m_can-base.yaml", "pinctrl-device.yaml"] properties: reg: diff --git a/dts/bindings/can/st,stm32h7-fdcan.yaml b/dts/bindings/can/st,stm32h7-fdcan.yaml index 9f9f0250312..5679141fe8e 100644 --- a/dts/bindings/can/st,stm32h7-fdcan.yaml +++ b/dts/bindings/can/st,stm32h7-fdcan.yaml @@ -2,7 +2,7 @@ description: ST STM32H7 series FDCAN CAN-FD controller compatible: "st,stm32h7-fdcan" -include: ["can-fd-controller.yaml", "pinctrl-device.yaml"] +include: ["bosch,m_can-base.yaml", "pinctrl-device.yaml"] properties: clocks: