drivers: can: mcan: let front-end drivers supply message RAM functions
Let the Bosch M_CAN front-end drivers supply their own Message RAM read/write/clear functions. This is preparation for supporting per-instance Bosch M_CAN Message RAM layouts and for accessing Bosch M_CAN IP cores over peripheral busses. Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
parent
6cd67e67fe
commit
3ed354eea1
7 changed files with 816 additions and 246 deletions
|
@ -5,7 +5,6 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/cache.h>
|
||||
#include <zephyr/drivers/can.h>
|
||||
#include <zephyr/drivers/can/transceiver.h>
|
||||
#include <zephyr/kernel.h>
|
||||
|
@ -19,39 +18,12 @@ LOG_MODULE_REGISTER(can_mcan, CONFIG_CAN_LOG_LEVEL);
|
|||
|
||||
#define CAN_INIT_TIMEOUT_MS 100
|
||||
|
||||
static void memcpy32_volatile(volatile void *dst_, const volatile void *src_, size_t len)
|
||||
{
|
||||
volatile uint32_t *dst = dst_;
|
||||
const volatile uint32_t *src = src_;
|
||||
|
||||
__ASSERT(len % 4 == 0U, "len must be a multiple of 4!");
|
||||
len /= sizeof(uint32_t);
|
||||
|
||||
while (len--) {
|
||||
*dst = *src;
|
||||
++dst;
|
||||
++src;
|
||||
}
|
||||
}
|
||||
|
||||
static void memset32_volatile(volatile void *dst_, uint32_t val, size_t len)
|
||||
{
|
||||
volatile uint32_t *dst = dst_;
|
||||
|
||||
__ASSERT(len % 4 == 0U, "len must be a multiple of 4!");
|
||||
len /= sizeof(uint32_t);
|
||||
|
||||
while (len--) {
|
||||
*dst++ = val;
|
||||
}
|
||||
}
|
||||
|
||||
int can_mcan_read_reg(const struct device *dev, uint16_t reg, uint32_t *val)
|
||||
{
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
int err;
|
||||
|
||||
err = config->read_reg(dev, reg, val);
|
||||
err = config->ops->read_reg(dev, reg, val);
|
||||
if (err != 0) {
|
||||
LOG_ERR("failed to read reg 0x%03x (err %d)", reg, err);
|
||||
} else {
|
||||
|
@ -66,7 +38,7 @@ int can_mcan_write_reg(const struct device *dev, uint16_t reg, uint32_t val)
|
|||
const struct can_mcan_config *config = dev->config;
|
||||
int err;
|
||||
|
||||
err = config->write_reg(dev, reg, val);
|
||||
err = config->ops->write_reg(dev, reg, val);
|
||||
if (err != 0) {
|
||||
LOG_ERR("failed to write reg 0x%03x (err %d)", reg, err);
|
||||
} else {
|
||||
|
@ -505,8 +477,7 @@ static void can_mcan_state_change_handler(const struct device *dev)
|
|||
static void can_mcan_tc_event_handler(const struct device *dev)
|
||||
{
|
||||
struct can_mcan_data *data = dev->data;
|
||||
struct can_mcan_msg_sram *msg_ram = data->msg_ram;
|
||||
volatile struct can_mcan_tx_event_fifo *tx_event;
|
||||
struct can_mcan_tx_event_fifo tx_event;
|
||||
can_tx_callback_t tx_cb;
|
||||
uint32_t event_idx;
|
||||
uint32_t tx_idx;
|
||||
|
@ -520,10 +491,17 @@ 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);
|
||||
sys_cache_data_invd_range((void *)&msg_ram->tx_event_fifo[event_idx],
|
||||
sizeof(struct can_mcan_tx_event_fifo));
|
||||
tx_event = &msg_ram->tx_event_fifo[event_idx];
|
||||
tx_idx = tx_event->mm.idx;
|
||||
err = can_mcan_read_mram(dev, CAN_MCAN_MRAM_OFFSET_TX_EVENT_FIFO +
|
||||
event_idx * sizeof(struct can_mcan_tx_event_fifo),
|
||||
&tx_event,
|
||||
sizeof(struct can_mcan_tx_event_fifo));
|
||||
if (err != 0) {
|
||||
LOG_ERR("failed to read tx event fifo (err %d)", err);
|
||||
return;
|
||||
}
|
||||
|
||||
tx_idx = tx_event.mm.idx;
|
||||
|
||||
/* Acknowledge TX event */
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_TXEFA, event_idx);
|
||||
if (err != 0) {
|
||||
|
@ -592,7 +570,7 @@ void can_mcan_line_0_isr(const struct device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
static void can_mcan_get_message(const struct device *dev, volatile struct can_mcan_rx_fifo *fifo,
|
||||
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;
|
||||
|
@ -613,12 +591,17 @@ static void can_mcan_get_message(const struct device *dev, volatile struct can_m
|
|||
return;
|
||||
}
|
||||
|
||||
while ((fifo_status & CAN_MCAN_RXF0S_F0FL) != 0U) {
|
||||
while (FIELD_GET(CAN_MCAN_RXF0S_F0FL, fifo_status) != 0U) {
|
||||
get_idx = FIELD_GET(CAN_MCAN_RXF0S_F0GI, fifo_status);
|
||||
|
||||
sys_cache_data_invd_range((void *)&fifo[get_idx].hdr,
|
||||
sizeof(struct can_mcan_rx_fifo_hdr));
|
||||
memcpy32_volatile(&hdr, &fifo[get_idx].hdr, sizeof(struct can_mcan_rx_fifo_hdr));
|
||||
err = can_mcan_read_mram(dev, fifo_offset + get_idx *
|
||||
sizeof(struct can_mcan_rx_fifo) +
|
||||
offsetof(struct can_mcan_rx_fifo, hdr),
|
||||
&hdr, sizeof(struct can_mcan_rx_fifo_hdr));
|
||||
if (err != 0) {
|
||||
LOG_ERR("failed to read Rx FIFO header (err %d)", err);
|
||||
return;
|
||||
}
|
||||
|
||||
frame.dlc = hdr.dlc;
|
||||
|
||||
|
@ -675,11 +658,15 @@ static void can_mcan_get_message(const struct device *dev, volatile struct can_m
|
|||
|
||||
data_length = can_dlc_to_bytes(frame.dlc);
|
||||
if (data_length <= sizeof(frame.data)) {
|
||||
/* Data needs to be written in 32 bit blocks! */
|
||||
sys_cache_data_invd_range((void *)fifo[get_idx].data_32,
|
||||
ROUND_UP(data_length, sizeof(uint32_t)));
|
||||
memcpy32_volatile(frame.data_32, fifo[get_idx].data_32,
|
||||
ROUND_UP(data_length, sizeof(uint32_t)));
|
||||
err = can_mcan_read_mram(dev, fifo_offset + get_idx *
|
||||
sizeof(struct can_mcan_rx_fifo) +
|
||||
offsetof(struct can_mcan_rx_fifo, data_32),
|
||||
&frame.data_32,
|
||||
ROUND_UP(data_length, sizeof(uint32_t)));
|
||||
if (err != 0) {
|
||||
LOG_ERR("failed to read Rx FIFO data (err %d)", err);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((frame.flags & CAN_FRAME_IDE) != 0) {
|
||||
LOG_DBG("Frame on filter %d, ID: 0x%x",
|
||||
|
@ -718,8 +705,6 @@ void can_mcan_line_1_isr(const struct device *dev)
|
|||
{
|
||||
const uint32_t events =
|
||||
CAN_MCAN_IR_RF0N | CAN_MCAN_IR_RF1N | CAN_MCAN_IR_RF0L | CAN_MCAN_IR_RF1L;
|
||||
struct can_mcan_data *data = dev->data;
|
||||
struct can_mcan_msg_sram *msg_ram = data->msg_ram;
|
||||
uint32_t ir;
|
||||
int err;
|
||||
|
||||
|
@ -731,13 +716,13 @@ 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, msg_ram->rx_fifo0, CAN_MCAN_RXF0S,
|
||||
can_mcan_get_message(dev, CAN_MCAN_MRAM_OFFSET_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, msg_ram->rx_fifo1, CAN_MCAN_RXF1S,
|
||||
can_mcan_get_message(dev, CAN_MCAN_MRAM_OFFSET_RX_FIFO1, CAN_MCAN_RXF1S,
|
||||
CAN_MCAN_RXF1A);
|
||||
}
|
||||
|
||||
|
@ -817,7 +802,6 @@ int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_tim
|
|||
can_tx_callback_t callback, void *user_data)
|
||||
{
|
||||
struct can_mcan_data *data = dev->data;
|
||||
struct can_mcan_msg_sram *msg_ram = data->msg_ram;
|
||||
size_t data_length = can_dlc_to_bytes(frame->dlc);
|
||||
struct can_mcan_tx_buffer_hdr tx_hdr = {
|
||||
.rtr = (frame->flags & CAN_FRAME_RTR) != 0U ? 1U : 0U,
|
||||
|
@ -921,12 +905,23 @@ 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;
|
||||
}
|
||||
|
||||
memcpy32_volatile(&msg_ram->tx_buffer[put_idx].hdr, &tx_hdr, sizeof(tx_hdr));
|
||||
memcpy32_volatile(msg_ram->tx_buffer[put_idx].data_32, frame->data_32,
|
||||
ROUND_UP(data_length, 4));
|
||||
sys_cache_data_flush_range((void *)&msg_ram->tx_buffer[put_idx].hdr, sizeof(tx_hdr));
|
||||
sys_cache_data_flush_range((void *)&msg_ram->tx_buffer[put_idx].data_32,
|
||||
ROUND_UP(data_length, 4));
|
||||
err = can_mcan_write_mram(dev, CAN_MCAN_MRAM_OFFSET_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));
|
||||
if (err != 0) {
|
||||
LOG_ERR("failed to write Tx Buffer header (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = can_mcan_write_mram(dev, CAN_MCAN_MRAM_OFFSET_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)));
|
||||
if (err != 0) {
|
||||
LOG_ERR("failed to write Tx Buffer data (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
data->tx_fin_cb[put_idx] = callback;
|
||||
data->tx_fin_cb_arg[put_idx] = user_data;
|
||||
|
@ -942,12 +937,22 @@ unlock:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int can_mcan_get_free_std(volatile struct can_mcan_std_filter *filters)
|
||||
static int can_mcan_get_free_std(const struct device *dev)
|
||||
{
|
||||
struct can_mcan_std_filter filter;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_STD_FILTER_DATA; ++i) {
|
||||
if (filters[i].sfce == CAN_MCAN_FCE_DISABLE) {
|
||||
err = can_mcan_read_mram(dev, CAN_MCAN_MRAM_OFFSET_STD_FILTER +
|
||||
i * sizeof(struct can_mcan_std_filter), &filter,
|
||||
sizeof(struct can_mcan_std_filter));
|
||||
if (err != 0) {
|
||||
LOG_ERR("failed to read std filter (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (filter.sfce == CAN_MCAN_FCE_DISABLE) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -975,15 +980,18 @@ int can_mcan_add_rx_filter_std(const struct device *dev, can_rx_callback_t callb
|
|||
void *user_data, const struct can_filter *filter)
|
||||
{
|
||||
struct can_mcan_data *data = dev->data;
|
||||
struct can_mcan_msg_sram *msg_ram = data->msg_ram;
|
||||
struct can_mcan_std_filter filter_element = {
|
||||
.id1 = filter->id, .id2 = filter->mask, .sft = CAN_MCAN_SFT_MASKED};
|
||||
.id1 = filter->id,
|
||||
.id2 = filter->mask,
|
||||
.sft = CAN_MCAN_SFT_MASKED
|
||||
};
|
||||
int filter_id;
|
||||
int err;
|
||||
|
||||
k_mutex_lock(&data->lock, K_FOREVER);
|
||||
filter_id = can_mcan_get_free_std(msg_ram->std_filt);
|
||||
filter_id = can_mcan_get_free_std(dev);
|
||||
|
||||
if (filter_id == -ENOSPC) {
|
||||
if (filter_id < 0) {
|
||||
LOG_WRN("No free standard id filter left");
|
||||
k_mutex_unlock(&data->lock);
|
||||
return -ENOSPC;
|
||||
|
@ -992,10 +1000,13 @@ 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;
|
||||
|
||||
memcpy32_volatile(&msg_ram->std_filt[filter_id], &filter_element,
|
||||
sizeof(struct can_mcan_std_filter));
|
||||
sys_cache_data_flush_range((void *)&msg_ram->std_filt[filter_id],
|
||||
sizeof(struct can_mcan_std_filter));
|
||||
err = can_mcan_write_mram(dev, CAN_MCAN_MRAM_OFFSET_STD_FILTER +
|
||||
filter_id * sizeof(struct can_mcan_std_filter),
|
||||
&filter_element, sizeof(filter_element));
|
||||
if (err != 0) {
|
||||
LOG_ERR("failed to write std filter element (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
k_mutex_unlock(&data->lock);
|
||||
|
||||
|
@ -1026,12 +1037,22 @@ int can_mcan_add_rx_filter_std(const struct device *dev, can_rx_callback_t callb
|
|||
return filter_id;
|
||||
}
|
||||
|
||||
static int can_mcan_get_free_ext(volatile struct can_mcan_ext_filter *filters)
|
||||
static int can_mcan_get_free_ext(const struct device *dev)
|
||||
{
|
||||
struct can_mcan_ext_filter filter;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_EXT_FILTER_DATA; ++i) {
|
||||
if (filters[i].efce == CAN_MCAN_FCE_DISABLE) {
|
||||
err = can_mcan_read_mram(dev, CAN_MCAN_MRAM_OFFSET_EXT_FILTER +
|
||||
i * sizeof(struct can_mcan_ext_filter), &filter,
|
||||
sizeof(struct can_mcan_ext_filter));
|
||||
if (err != 0) {
|
||||
LOG_ERR("failed to read ext filter (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (filter.efce == CAN_MCAN_FCE_DISABLE) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -1043,15 +1064,18 @@ static int can_mcan_add_rx_filter_ext(const struct device *dev, can_rx_callback_
|
|||
void *user_data, const struct can_filter *filter)
|
||||
{
|
||||
struct can_mcan_data *data = dev->data;
|
||||
struct can_mcan_msg_sram *msg_ram = data->msg_ram;
|
||||
struct can_mcan_ext_filter filter_element = {
|
||||
.id2 = filter->mask, .id1 = filter->id, .eft = CAN_MCAN_EFT_MASKED};
|
||||
.id2 = filter->mask,
|
||||
.id1 = filter->id,
|
||||
.eft = CAN_MCAN_EFT_MASKED
|
||||
};
|
||||
int filter_id;
|
||||
int err;
|
||||
|
||||
k_mutex_lock(&data->lock, K_FOREVER);
|
||||
filter_id = can_mcan_get_free_ext(msg_ram->ext_filt);
|
||||
filter_id = can_mcan_get_free_ext(dev);
|
||||
|
||||
if (filter_id == -ENOSPC) {
|
||||
if (filter_id < 0) {
|
||||
LOG_WRN("No free extended id filter left");
|
||||
k_mutex_unlock(&data->lock);
|
||||
return -ENOSPC;
|
||||
|
@ -1060,10 +1084,13 @@ 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;
|
||||
|
||||
memcpy32_volatile(&msg_ram->ext_filt[filter_id], &filter_element,
|
||||
sizeof(struct can_mcan_ext_filter));
|
||||
sys_cache_data_flush_range((void *)&msg_ram->ext_filt[filter_id],
|
||||
sizeof(struct can_mcan_ext_filter));
|
||||
err = can_mcan_write_mram(dev, CAN_MCAN_MRAM_OFFSET_EXT_FILTER +
|
||||
filter_id * sizeof(struct can_mcan_ext_filter),
|
||||
&filter_element, sizeof(filter_element));
|
||||
if (err != 0) {
|
||||
LOG_ERR("failed to write std filter element (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
k_mutex_unlock(&data->lock);
|
||||
|
||||
|
@ -1128,7 +1155,7 @@ 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)
|
||||
{
|
||||
struct can_mcan_data *data = dev->data;
|
||||
struct can_mcan_msg_sram *msg_ram = data->msg_ram;
|
||||
int err;
|
||||
|
||||
k_mutex_lock(&data->lock, K_FOREVER);
|
||||
|
||||
|
@ -1140,15 +1167,19 @@ void can_mcan_remove_rx_filter(const struct device *dev, int filter_id)
|
|||
return;
|
||||
}
|
||||
|
||||
memset32_volatile(&msg_ram->ext_filt[filter_id], 0,
|
||||
sizeof(struct can_mcan_ext_filter));
|
||||
sys_cache_data_flush_range((void *)&msg_ram->ext_filt[filter_id],
|
||||
sizeof(struct can_mcan_ext_filter));
|
||||
err = can_mcan_clear_mram(dev, CAN_MCAN_MRAM_OFFSET_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 {
|
||||
memset32_volatile(&msg_ram->std_filt[filter_id], 0,
|
||||
sizeof(struct can_mcan_std_filter));
|
||||
sys_cache_data_flush_range((void *)&msg_ram->std_filt[filter_id],
|
||||
sizeof(struct can_mcan_std_filter));
|
||||
err = can_mcan_clear_mram(dev, CAN_MCAN_MRAM_OFFSET_STD_FILTER +
|
||||
filter_id * sizeof(struct can_mcan_std_filter),
|
||||
sizeof(struct can_mcan_std_filter));
|
||||
if (err != 0) {
|
||||
LOG_ERR("failed to clear std filter element (err %d)", err);
|
||||
}
|
||||
}
|
||||
|
||||
k_mutex_unlock(&data->lock);
|
||||
|
@ -1200,10 +1231,8 @@ unlock:
|
|||
k_mutex_unlock(&data->lock);
|
||||
}
|
||||
|
||||
int can_mcan_configure_message_ram(const struct device *dev, uintptr_t mrba)
|
||||
int can_mcan_configure_mram(const struct device *dev, uintptr_t mrba, uintptr_t mram)
|
||||
{
|
||||
struct can_mcan_data *data = dev->data;
|
||||
struct can_mcan_msg_sram *msg_ram = data->msg_ram;
|
||||
uint32_t reg;
|
||||
int err;
|
||||
|
||||
|
@ -1221,78 +1250,63 @@ int can_mcan_configure_message_ram(const struct device *dev, uintptr_t mrba)
|
|||
|
||||
can_mcan_enable_configuration_change(dev);
|
||||
|
||||
reg = ((POINTER_TO_UINT(msg_ram->std_filt) - mrba) & CAN_MCAN_SIDFC_FLSSA) |
|
||||
FIELD_PREP(CAN_MCAN_SIDFC_LSS, ARRAY_SIZE(msg_ram->std_filt));
|
||||
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_STD_FILTER) & CAN_MCAN_SIDFC_FLSSA) |
|
||||
FIELD_PREP(CAN_MCAN_SIDFC_LSS, NUM_STD_FILTER_ELEMENTS);
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_SIDFC, reg);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
reg = ((POINTER_TO_UINT(msg_ram->ext_filt) - mrba) & CAN_MCAN_XIDFC_FLESA) |
|
||||
FIELD_PREP(CAN_MCAN_XIDFC_LSS, ARRAY_SIZE(msg_ram->ext_filt));
|
||||
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_EXT_FILTER) & CAN_MCAN_XIDFC_FLESA) |
|
||||
FIELD_PREP(CAN_MCAN_XIDFC_LSS, NUM_EXT_FILTER_ELEMENTS);
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_XIDFC, reg);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
reg = ((POINTER_TO_UINT(msg_ram->rx_fifo0) - mrba) & CAN_MCAN_RXF0C_F0SA) |
|
||||
FIELD_PREP(CAN_MCAN_RXF0C_F0S, ARRAY_SIZE(msg_ram->rx_fifo0));
|
||||
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_RX_FIFO0) & CAN_MCAN_RXF0C_F0SA) |
|
||||
FIELD_PREP(CAN_MCAN_RXF0C_F0S, NUM_RX_FIFO0_ELEMENTS);
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_RXF0C, reg);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
reg = ((POINTER_TO_UINT(msg_ram->rx_fifo1) - mrba) & CAN_MCAN_RXF1C_F1SA) |
|
||||
FIELD_PREP(CAN_MCAN_RXF1C_F1S, ARRAY_SIZE(msg_ram->rx_fifo1));
|
||||
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_RX_FIFO1) & CAN_MCAN_RXF1C_F1SA) |
|
||||
FIELD_PREP(CAN_MCAN_RXF1C_F1S, NUM_RX_FIFO1_ELEMENTS);
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_RXF1C, reg);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
reg = ((POINTER_TO_UINT(msg_ram->rx_buffer) - mrba) & CAN_MCAN_RXBC_RBSA);
|
||||
reg = ((mram - mrba + CAN_MCAN_MRAM_OFFSET_RX_BUFFER) & CAN_MCAN_RXBC_RBSA);
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_RXBC, reg);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
reg = ((POINTER_TO_UINT(msg_ram->tx_event_fifo) - mrba) & CAN_MCAN_TXEFC_EFSA) |
|
||||
FIELD_PREP(CAN_MCAN_TXEFC_EFS, ARRAY_SIZE(msg_ram->tx_event_fifo));
|
||||
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);
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_TXEFC, reg);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
reg = ((POINTER_TO_UINT(msg_ram->tx_buffer) - mrba) & CAN_MCAN_TXBC_TBSA) |
|
||||
FIELD_PREP(CAN_MCAN_TXBC_TFQS, ARRAY_SIZE(msg_ram->tx_buffer)) | CAN_MCAN_TXBC_TFQM;
|
||||
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;
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_TXBC, reg);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (sizeof(msg_ram->tx_buffer[0].data) <= 24) {
|
||||
reg = (sizeof(msg_ram->tx_buffer[0].data) - 8) / 4;
|
||||
} else {
|
||||
reg = (sizeof(msg_ram->tx_buffer[0].data) - 32) / 16 + 5;
|
||||
}
|
||||
|
||||
/* 64 byte Tx Buffer data fields size */
|
||||
reg = CAN_MCAN_TXESC_TBDS;
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_TXESC, reg);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (sizeof(msg_ram->rx_fifo0[0].data) <= 24) {
|
||||
reg = FIELD_PREP(CAN_MCAN_RXESC_F0DS, (sizeof(msg_ram->rx_fifo0[0].data) - 8) / 4) |
|
||||
FIELD_PREP(CAN_MCAN_RXESC_F1DS, (sizeof(msg_ram->rx_fifo1[0].data) - 8) / 4) |
|
||||
FIELD_PREP(CAN_MCAN_RXESC_RBDS, (sizeof(msg_ram->rx_buffer[0].data) - 8) / 4);
|
||||
} else {
|
||||
reg = FIELD_PREP(CAN_MCAN_RXESC_F0DS,
|
||||
(sizeof(msg_ram->rx_fifo0[0].data) - 32) / 16 + 5) |
|
||||
FIELD_PREP(CAN_MCAN_RXESC_F1DS,
|
||||
(sizeof(msg_ram->rx_fifo1[0].data) - 32) / 16 + 5) |
|
||||
FIELD_PREP(CAN_MCAN_RXESC_RBDS,
|
||||
(sizeof(msg_ram->rx_buffer[0].data) - 32) / 16 + 5);
|
||||
}
|
||||
|
||||
/* 64 byte Rx Buffer/FIFO1/FIFO0 data fields size */
|
||||
reg = CAN_MCAN_RXESC_RBDS | CAN_MCAN_RXESC_F1DS | CAN_MCAN_RXESC_F0DS;
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_RXESC, reg);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
|
@ -1305,7 +1319,6 @@ int can_mcan_init(const struct device *dev)
|
|||
{
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
struct can_mcan_data *data = dev->data;
|
||||
struct can_mcan_msg_sram *msg_ram = data->msg_ram;
|
||||
struct can_timing timing;
|
||||
#ifdef CONFIG_CAN_FD_MODE
|
||||
struct can_timing timing_data;
|
||||
|
@ -1313,6 +1326,12 @@ int can_mcan_init(const struct device *dev)
|
|||
uint32_t reg;
|
||||
int err;
|
||||
|
||||
__ASSERT_NO_MSG(config->ops->read_reg != NULL);
|
||||
__ASSERT_NO_MSG(config->ops->write_reg != NULL);
|
||||
__ASSERT_NO_MSG(config->ops->read_mram != NULL);
|
||||
__ASSERT_NO_MSG(config->ops->write_mram != NULL);
|
||||
__ASSERT_NO_MSG(config->ops->clear_mram != NULL);
|
||||
|
||||
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);
|
||||
|
@ -1488,8 +1507,5 @@ int can_mcan_init(const struct device *dev)
|
|||
return err;
|
||||
}
|
||||
|
||||
memset32_volatile(msg_ram, 0, sizeof(struct can_mcan_msg_sram));
|
||||
sys_cache_data_flush_range(msg_ram, sizeof(struct can_mcan_msg_sram));
|
||||
|
||||
return 0;
|
||||
return can_mcan_clear_mram(dev, 0, sizeof(struct can_mcan_msg_sram));
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#ifndef ZEPHYR_DRIVERS_CAN_MCAN_H_
|
||||
#define ZEPHYR_DRIVERS_CAN_MCAN_H_
|
||||
|
||||
#include <zephyr/cache.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
#include <zephyr/drivers/can.h>
|
||||
#include <zephyr/kernel.h>
|
||||
|
@ -389,13 +390,173 @@
|
|||
#define MCAN_DT_PATH DT_PATH(soc, can)
|
||||
#endif
|
||||
|
||||
#define NUM_STD_FILTER_ELEMENTS DT_PROP_BY_IDX(MCAN_DT_PATH, bosch_mram_cfg, 1)
|
||||
#define NUM_EXT_FILTER_ELEMENTS DT_PROP_BY_IDX(MCAN_DT_PATH, bosch_mram_cfg, 2)
|
||||
#define NUM_RX_FIFO0_ELEMENTS DT_PROP_BY_IDX(MCAN_DT_PATH, bosch_mram_cfg, 3)
|
||||
#define NUM_RX_FIFO1_ELEMENTS DT_PROP_BY_IDX(MCAN_DT_PATH, bosch_mram_cfg, 4)
|
||||
#define NUM_RX_BUF_ELEMENTS DT_PROP_BY_IDX(MCAN_DT_PATH, bosch_mram_cfg, 5)
|
||||
#define NUM_TX_EVENT_FIFO_ELEMENTS DT_PROP_BY_IDX(MCAN_DT_PATH, bosch_mram_cfg, 6)
|
||||
#define NUM_TX_BUF_ELEMENTS DT_PROP_BY_IDX(MCAN_DT_PATH, bosch_mram_cfg, 7)
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
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
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get the Bosch M_CAN Message RAM offset
|
||||
*
|
||||
* @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)
|
||||
|
||||
/**
|
||||
* @brief Get the number of standard (11-bit) filter elements in Bosch M_CAN Message RAM
|
||||
*
|
||||
* @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)
|
||||
|
||||
/**
|
||||
* @brief Get the number of extended (29-bit) filter elements in Bosch M_CAN Message RAM
|
||||
*
|
||||
* @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)
|
||||
|
||||
/**
|
||||
* @brief Get the number of Rx FIFO 0 elements in Bosch M_CAN Message RAM
|
||||
*
|
||||
* @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)
|
||||
|
||||
/**
|
||||
* @brief Get the number of Rx FIFO 1 elements in Bosch M_CAN Message RAM
|
||||
*
|
||||
* @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)
|
||||
|
||||
/**
|
||||
* @brief Get the number of Rx Buffer elements in Bosch M_CAN Message RAM
|
||||
*
|
||||
* @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)
|
||||
|
||||
/**
|
||||
* @brief Get the number of Tx Event FIFO elements in Bosch M_CAN Message RAM
|
||||
*
|
||||
* @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)
|
||||
|
||||
/**
|
||||
* @brief Get the number of Tx Buffer elements in Bosch M_CAN Message RAM
|
||||
*
|
||||
* @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)
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_OFFSET(DT_DRV_INST(inst))
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @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))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_STD_FILTER_ELEM(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()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_STD_FILTER_ELEM(inst) \
|
||||
CAN_MCAN_DT_MRAM_STD_FILTER_ELEMDT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_EXT_FILTER_ELEM(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()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_EXT_FILTER_ELEM(inst) \
|
||||
CAN_MCAN_DT_MRAM_EXT_FILTER_ELEM(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_FIFO0_ELEM(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()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_RX_FIFO0_ELEM(inst) \
|
||||
CAN_MCAN_DT_MRAM_RX_FIFO0_ELEM(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_FIFO1_ELEM(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()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_RX_FIFO1_ELEM(inst) \
|
||||
CAN_MCAN_DT_MRAM_RX_FIFO1_ELEM(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_RX_BUFFER_ELEM(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()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_RX_BUFFER_ELEM(inst) \
|
||||
CAN_MCAN_DT_MRAM_RX_BUFFER_ELEM(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_TX_EVENT_ELEM(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()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_TX_EVENT_FIFO_ELEM(inst) \
|
||||
CAN_MCAN_DT_MRAM_TX_EVENT_FIFO_ELEM(DT_DRV_INST(inst))
|
||||
|
||||
/**
|
||||
* @brief Equivalent to CAN_MCAN_DT_MRAM_TX_BUFFER_ELEM(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()
|
||||
*/
|
||||
#define CAN_MCAN_DT_INST_MRAM_TX_BUFFER_ELEM(inst) \
|
||||
CAN_MCAN_DT_MRAM_TX_BUFFER_ELEM(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)
|
||||
|
||||
#ifdef CONFIG_CAN_STM32FD
|
||||
#define NUM_STD_FILTER_DATA CONFIG_CAN_MAX_STD_ID_FILTER
|
||||
|
@ -408,68 +569,68 @@
|
|||
struct can_mcan_rx_fifo_hdr {
|
||||
union {
|
||||
struct {
|
||||
volatile uint32_t ext_id: 29; /* Extended Identifier */
|
||||
volatile uint32_t rtr: 1; /* Remote Transmission Request*/
|
||||
volatile uint32_t xtd: 1; /* Extended identifier */
|
||||
volatile uint32_t esi: 1; /* Error state indicator */
|
||||
uint32_t ext_id: 29; /* Extended Identifier */
|
||||
uint32_t rtr: 1; /* Remote Transmission Request*/
|
||||
uint32_t xtd: 1; /* Extended identifier */
|
||||
uint32_t esi: 1; /* Error state indicator */
|
||||
};
|
||||
struct {
|
||||
volatile uint32_t pad1: 18;
|
||||
volatile uint32_t std_id: 11; /* Standard Identifier */
|
||||
volatile uint32_t pad2: 3;
|
||||
uint32_t pad1: 18;
|
||||
uint32_t std_id: 11; /* Standard Identifier */
|
||||
uint32_t pad2: 3;
|
||||
};
|
||||
};
|
||||
|
||||
volatile uint32_t rxts: 16; /* Rx timestamp */
|
||||
volatile uint32_t dlc: 4; /* Data Length Code */
|
||||
volatile uint32_t brs: 1; /* Bit Rate Switch */
|
||||
volatile uint32_t fdf: 1; /* FD Format */
|
||||
volatile uint32_t res: 2; /* Reserved */
|
||||
volatile uint32_t fidx: 7; /* Filter Index */
|
||||
volatile uint32_t anmf: 1; /* Accepted non-matching frame */
|
||||
uint32_t rxts: 16; /* Rx timestamp */
|
||||
uint32_t dlc: 4; /* Data Length Code */
|
||||
uint32_t brs: 1; /* Bit Rate Switch */
|
||||
uint32_t fdf: 1; /* FD Format */
|
||||
uint32_t res: 2; /* Reserved */
|
||||
uint32_t fidx: 7; /* Filter Index */
|
||||
uint32_t anmf: 1; /* Accepted non-matching frame */
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct can_mcan_rx_fifo {
|
||||
struct can_mcan_rx_fifo_hdr hdr;
|
||||
union {
|
||||
volatile uint8_t data[64];
|
||||
volatile uint32_t data_32[16];
|
||||
uint8_t data[64];
|
||||
uint32_t data_32[16];
|
||||
};
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct can_mcan_mm {
|
||||
volatile uint8_t idx: 5;
|
||||
volatile uint8_t cnt: 3;
|
||||
uint8_t idx: 5;
|
||||
uint8_t cnt: 3;
|
||||
} __packed;
|
||||
|
||||
struct can_mcan_tx_buffer_hdr {
|
||||
union {
|
||||
struct {
|
||||
volatile uint32_t ext_id: 29; /* Identifier */
|
||||
volatile uint32_t rtr: 1; /* Remote Transmission Request*/
|
||||
volatile uint32_t xtd: 1; /* Extended identifier */
|
||||
volatile uint32_t esi: 1; /* Error state indicator */
|
||||
uint32_t ext_id: 29; /* Identifier */
|
||||
uint32_t rtr: 1; /* Remote Transmission Request*/
|
||||
uint32_t xtd: 1; /* Extended identifier */
|
||||
uint32_t esi: 1; /* Error state indicator */
|
||||
};
|
||||
struct {
|
||||
volatile uint32_t pad1: 18;
|
||||
volatile uint32_t std_id: 11; /* Identifier */
|
||||
volatile uint32_t pad2: 3;
|
||||
uint32_t pad1: 18;
|
||||
uint32_t std_id: 11; /* Identifier */
|
||||
uint32_t pad2: 3;
|
||||
};
|
||||
};
|
||||
volatile uint16_t res1; /* Reserved */
|
||||
volatile uint8_t dlc: 4; /* Data Length Code */
|
||||
volatile uint8_t brs: 1; /* Bit Rate Switch */
|
||||
volatile uint8_t fdf: 1; /* FD Format */
|
||||
volatile uint8_t res2: 1; /* Reserved */
|
||||
volatile uint8_t efc: 1; /* Event FIFO control (Store Tx events) */
|
||||
uint16_t res1; /* Reserved */
|
||||
uint8_t dlc: 4; /* Data Length Code */
|
||||
uint8_t brs: 1; /* Bit Rate Switch */
|
||||
uint8_t fdf: 1; /* FD Format */
|
||||
uint8_t res2: 1; /* Reserved */
|
||||
uint8_t efc: 1; /* Event FIFO control (Store Tx events) */
|
||||
struct can_mcan_mm mm; /* Message marker */
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct can_mcan_tx_buffer {
|
||||
struct can_mcan_tx_buffer_hdr hdr;
|
||||
union {
|
||||
volatile uint8_t data[64];
|
||||
volatile uint32_t data_32[16];
|
||||
uint8_t data[64];
|
||||
uint32_t data_32[16];
|
||||
};
|
||||
} __packed __aligned(4);
|
||||
|
||||
|
@ -477,16 +638,16 @@ struct can_mcan_tx_buffer {
|
|||
#define CAN_MCAN_TE_TXC 0x2 /* TX event in spite of cancellation */
|
||||
|
||||
struct can_mcan_tx_event_fifo {
|
||||
volatile uint32_t id: 29; /* Identifier */
|
||||
volatile uint32_t rtr: 1; /* Remote Transmission Request*/
|
||||
volatile uint32_t xtd: 1; /* Extended identifier */
|
||||
volatile uint32_t esi: 1; /* Error state indicator */
|
||||
uint32_t id: 29; /* Identifier */
|
||||
uint32_t rtr: 1; /* Remote Transmission Request*/
|
||||
uint32_t xtd: 1; /* Extended identifier */
|
||||
uint32_t esi: 1; /* Error state indicator */
|
||||
|
||||
volatile uint16_t txts; /* TX Timestamp */
|
||||
volatile uint8_t dlc: 4; /* Data Length Code */
|
||||
volatile uint8_t brs: 1; /* Bit Rate Switch */
|
||||
volatile uint8_t fdf: 1; /* FD Format */
|
||||
volatile uint8_t et: 2; /* Event type */
|
||||
uint16_t txts; /* TX Timestamp */
|
||||
uint8_t dlc: 4; /* Data Length Code */
|
||||
uint8_t brs: 1; /* Bit Rate Switch */
|
||||
uint8_t fdf: 1; /* FD Format */
|
||||
uint8_t et: 2; /* Event type */
|
||||
struct can_mcan_mm mm; /* Message marker */
|
||||
} __packed __aligned(4);
|
||||
|
||||
|
@ -504,11 +665,11 @@ struct can_mcan_tx_event_fifo {
|
|||
#define CAN_MCAN_SFT_DISABLED 0x3
|
||||
|
||||
struct can_mcan_std_filter {
|
||||
volatile uint32_t id2: 11; /* ID2 for dual or range, mask otherwise */
|
||||
volatile uint32_t res: 5;
|
||||
volatile uint32_t id1: 11;
|
||||
volatile uint32_t sfce: 3; /* Filter config */
|
||||
volatile uint32_t sft: 2; /* Filter type */
|
||||
uint32_t id2: 11; /* ID2 for dual or range, mask otherwise */
|
||||
uint32_t res: 5;
|
||||
uint32_t id1: 11;
|
||||
uint32_t sfce: 3; /* Filter config */
|
||||
uint32_t sft: 2; /* Filter type */
|
||||
} __packed __aligned(4);
|
||||
|
||||
#define CAN_MCAN_EFT_RANGE_XIDAM 0x0
|
||||
|
@ -517,25 +678,32 @@ struct can_mcan_std_filter {
|
|||
#define CAN_MCAN_EFT_RANGE 0x3
|
||||
|
||||
struct can_mcan_ext_filter {
|
||||
volatile uint32_t id1: 29;
|
||||
volatile uint32_t efce: 3; /* Filter config */
|
||||
volatile uint32_t id2: 29; /* ID2 for dual or range, mask otherwise */
|
||||
volatile uint32_t res: 1;
|
||||
volatile uint32_t eft: 2; /* Filter type */
|
||||
uint32_t id1: 29;
|
||||
uint32_t efce: 3; /* Filter config */
|
||||
uint32_t id2: 29; /* ID2 for dual or range, mask otherwise */
|
||||
uint32_t res: 1;
|
||||
uint32_t eft: 2; /* Filter type */
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct can_mcan_msg_sram {
|
||||
volatile struct can_mcan_std_filter std_filt[NUM_STD_FILTER_ELEMENTS];
|
||||
volatile struct can_mcan_ext_filter ext_filt[NUM_EXT_FILTER_ELEMENTS];
|
||||
volatile struct can_mcan_rx_fifo rx_fifo0[NUM_RX_FIFO0_ELEMENTS];
|
||||
volatile struct can_mcan_rx_fifo rx_fifo1[NUM_RX_FIFO1_ELEMENTS];
|
||||
volatile struct can_mcan_rx_fifo rx_buffer[NUM_RX_BUF_ELEMENTS];
|
||||
volatile struct can_mcan_tx_event_fifo tx_event_fifo[NUM_TX_EVENT_FIFO_ELEMENTS];
|
||||
volatile struct can_mcan_tx_buffer tx_buffer[NUM_TX_BUF_ELEMENTS];
|
||||
struct can_mcan_std_filter std_filt[NUM_STD_FILTER_ELEMENTS];
|
||||
struct can_mcan_ext_filter ext_filt[NUM_EXT_FILTER_ELEMENTS];
|
||||
struct can_mcan_rx_fifo rx_fifo0[NUM_RX_FIFO0_ELEMENTS];
|
||||
struct can_mcan_rx_fifo rx_fifo1[NUM_RX_FIFO1_ELEMENTS];
|
||||
struct can_mcan_rx_fifo rx_buffer[NUM_RX_BUF_ELEMENTS];
|
||||
struct can_mcan_tx_event_fifo tx_event_fifo[NUM_TX_EVENT_FIFO_ELEMENTS];
|
||||
struct can_mcan_tx_buffer tx_buffer[NUM_TX_BUF_ELEMENTS];
|
||||
} __packed __aligned(4);
|
||||
|
||||
#define CAN_MCAN_MRAM_OFFSET_STD_FILTER offsetof(struct can_mcan_msg_sram, std_filt)
|
||||
#define CAN_MCAN_MRAM_OFFSET_EXT_FILTER offsetof(struct can_mcan_msg_sram, ext_filt)
|
||||
#define CAN_MCAN_MRAM_OFFSET_RX_FIFO0 offsetof(struct can_mcan_msg_sram, rx_fifo0)
|
||||
#define CAN_MCAN_MRAM_OFFSET_RX_FIFO1 offsetof(struct can_mcan_msg_sram, rx_fifo1)
|
||||
#define CAN_MCAN_MRAM_OFFSET_RX_BUFFER offsetof(struct can_mcan_msg_sram, rx_buffer)
|
||||
#define CAN_MCAN_MRAM_OFFSET_TX_EVENT_FIFO offsetof(struct can_mcan_msg_sram, tx_event_fifo)
|
||||
#define CAN_MCAN_MRAM_OFFSET_TX_BUFFER offsetof(struct can_mcan_msg_sram, tx_buffer)
|
||||
|
||||
struct can_mcan_data {
|
||||
struct can_mcan_msg_sram *msg_ram;
|
||||
struct k_mutex lock;
|
||||
struct k_sem tx_sem;
|
||||
struct k_mutex tx_mtx;
|
||||
|
@ -587,16 +755,71 @@ typedef int (*can_mcan_read_reg_t)(const struct device *dev, uint16_t reg, uint3
|
|||
*/
|
||||
typedef int (*can_mcan_write_reg_t)(const struct device *dev, uint16_t reg, uint32_t val);
|
||||
|
||||
struct can_mcan_config {
|
||||
/**
|
||||
* @brief Bosch M_CAN driver front-end callback for reading from Message RAM
|
||||
*
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
* @param offset Offset from the start of the Message RAM for the given Bosch M_CAN instance. The
|
||||
* offset must be 32-bit aligned.
|
||||
* @param[out] dst Destination for the data read. The destination address must be 32-bit aligned.
|
||||
* @param len Number of bytes to read. Must be a multiple of 4.
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO General input/output error.
|
||||
*/
|
||||
typedef int (*can_mcan_read_mram_t)(const struct device *dev, uint16_t offset, void *dst,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* @brief Bosch M_CAN driver front-end callback for writing to Message RAM
|
||||
*
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
* @param offset Offset from the start of the Message RAM for the given Bosch M_CAN instance. The
|
||||
* offset must be 32-bit aligned.
|
||||
* @param src Source for the data to be written. The source address must be 32-bit aligned.
|
||||
* @param len Number of bytes to write. Must be a multiple of 4.
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO General input/output error.
|
||||
*/
|
||||
typedef int (*can_mcan_write_mram_t)(const struct device *dev, uint16_t offset, const void *src,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* @brief Bosch M_CAN driver front-end callback for clearing Message RAM
|
||||
*
|
||||
* Clear Message RAM by writing 0 to all words.
|
||||
*
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
* @param offset Offset from the start of the Message RAM for the given Bosch M_CAN instance. The
|
||||
* offset must be 32-bit aligned.
|
||||
* @param len Number of bytes to clear. Must be a multiple of 4.
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO General input/output error.
|
||||
*/
|
||||
typedef int (*can_mcan_clear_mram_t)(const struct device *dev, uint16_t offset, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Bosch M_CAN driver front-end operations.
|
||||
*/
|
||||
struct can_mcan_ops {
|
||||
can_mcan_read_reg_t read_reg;
|
||||
can_mcan_write_reg_t write_reg;
|
||||
can_mcan_read_mram_t read_mram;
|
||||
can_mcan_write_mram_t write_mram;
|
||||
can_mcan_clear_mram_t clear_mram;
|
||||
};
|
||||
|
||||
struct can_mcan_config {
|
||||
struct can_mcan_ops *ops;
|
||||
uint32_t bus_speed;
|
||||
uint32_t bus_speed_data;
|
||||
uint16_t sjw;
|
||||
uint16_t sample_point;
|
||||
uint16_t prop_ts1;
|
||||
uint16_t ts2;
|
||||
#ifdef CONFIG_CAN_FD_MODE
|
||||
uint32_t bus_speed_data;
|
||||
uint16_t sample_point_data;
|
||||
uint8_t sjw_data;
|
||||
uint8_t prop_ts1_data;
|
||||
|
@ -613,14 +836,14 @@ struct can_mcan_config {
|
|||
*
|
||||
* @param node_id Devicetree node identifier
|
||||
* @param _custom Pointer to custom driver frontend configuration structure
|
||||
* @param _read_reg Driver frontend Bosch M_CAN register read function
|
||||
* @param _write_reg Driver frontend Bosch M_CAN register write function
|
||||
* @param _ops Pointer to front-end @a can_mcan_ops
|
||||
*/
|
||||
#ifdef CONFIG_CAN_FD_MODE
|
||||
#define CAN_MCAN_DT_CONFIG_GET(node_id, _custom, _read_reg, _write_reg) \
|
||||
#define CAN_MCAN_DT_CONFIG_GET(node_id, _custom, _ops) \
|
||||
{ \
|
||||
.read_reg = _read_reg, .write_reg = _write_reg, \
|
||||
.bus_speed = DT_PROP(node_id, bus_speed), .sjw = DT_PROP(node_id, sjw), \
|
||||
.ops = _ops, \
|
||||
.bus_speed = DT_PROP(node_id, bus_speed), \
|
||||
.sjw = DT_PROP(node_id, sjw), \
|
||||
.sample_point = DT_PROP_OR(node_id, sample_point, 0), \
|
||||
.prop_ts1 = DT_PROP_OR(node_id, prop_seg, 0) + DT_PROP_OR(node_id, phase_seg1, 0), \
|
||||
.ts2 = DT_PROP_OR(node_id, phase_seg2, 0), \
|
||||
|
@ -636,10 +859,11 @@ struct can_mcan_config {
|
|||
.custom = _custom, \
|
||||
}
|
||||
#else /* CONFIG_CAN_FD_MODE */
|
||||
#define CAN_MCAN_DT_CONFIG_GET(node_id, _custom, _read_reg, _write_reg) \
|
||||
#define CAN_MCAN_DT_CONFIG_GET(node_id, _custom, _ops) \
|
||||
{ \
|
||||
.read_reg = _read_reg, .write_reg = _write_reg, \
|
||||
.bus_speed = DT_PROP(node_id, bus_speed), .sjw = DT_PROP(node_id, sjw), \
|
||||
.ops = _ops, \
|
||||
.bus_speed = DT_PROP(node_id, bus_speed), \
|
||||
.sjw = DT_PROP(node_id, sjw), \
|
||||
.sample_point = DT_PROP_OR(node_id, sample_point, 0), \
|
||||
.prop_ts1 = DT_PROP_OR(node_id, prop_seg, 0) + DT_PROP_OR(node_id, phase_seg1, 0), \
|
||||
.ts2 = DT_PROP_OR(node_id, phase_seg2, 0), \
|
||||
|
@ -654,21 +878,20 @@ struct can_mcan_config {
|
|||
*
|
||||
* @param inst DT_DRV_COMPAT instance number
|
||||
* @param _custom Pointer to custom driver frontend configuration structure
|
||||
* @param _read_reg Driver frontend Bosch M_CAN register read function
|
||||
* @param _write_reg Driver frontend Bosch M_CAN register write function
|
||||
* @param _ops Pointer to front-end @a can_mcan_ops
|
||||
* @see CAN_MCAN_DT_CONFIG_GET()
|
||||
*/
|
||||
#define CAN_MCAN_DT_CONFIG_INST_GET(inst, _custom, _read_reg, _write_reg) \
|
||||
CAN_MCAN_DT_CONFIG_GET(DT_DRV_INST(inst), _custom, _read_reg, _write_reg)
|
||||
#define CAN_MCAN_DT_CONFIG_INST_GET(inst, _custom, _ops) \
|
||||
CAN_MCAN_DT_CONFIG_GET(DT_DRV_INST(inst), _custom, _ops)
|
||||
|
||||
/**
|
||||
* @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(_msg_ram, _custom) \
|
||||
#define CAN_MCAN_DATA_INITIALIZER(_custom) \
|
||||
{ \
|
||||
.msg_ram = _msg_ram, .custom = _custom, \
|
||||
.custom = _custom, \
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -703,6 +926,116 @@ static inline int can_mcan_sys_write_reg(mm_reg_t base, uint16_t reg, uint32_t v
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Bosch M_CAN driver front-end callback helper for reading from memory mapped Message RAM
|
||||
*
|
||||
* @param base Base address of the Message RAM for the given Bosch M_CAN instance. The base address
|
||||
* must be 32-bit aligned.
|
||||
* @param offset Offset from the start of the Message RAM for the given Bosch M_CAN instance. The
|
||||
* offset must be 32-bit aligned.
|
||||
* @param[out] dst Destination for the data read. The destination address must be 32-bit aligned.
|
||||
* @param len Number of bytes to read. Must be a multiple of 4.
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO General input/output error.
|
||||
*/
|
||||
static inline int can_mcan_sys_read_mram(mem_addr_t base, uint16_t offset, void *dst, size_t len)
|
||||
{
|
||||
volatile uint32_t *src32 = (volatile uint32_t *)(base + offset);
|
||||
uint32_t *dst32 = (uint32_t *)dst;
|
||||
size_t len32 = len / sizeof(uint32_t);
|
||||
|
||||
__ASSERT(base % 4U == 0U, "base must be a multiple of 4");
|
||||
__ASSERT(offset % 4U == 0U, "offset must be a multiple of 4");
|
||||
__ASSERT(POINTER_TO_UINT(dst) % 4U == 0U, "dst must be 32-bit aligned");
|
||||
__ASSERT(len % 4U == 0U, "len must be a multiple of 4");
|
||||
|
||||
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
|
||||
int err;
|
||||
|
||||
err = sys_cache_data_invd_range((void *)(base + offset), len);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
#endif /* !defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE) */
|
||||
|
||||
while (len32-- > 0) {
|
||||
*dst32++ = *src32++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Bosch M_CAN driver front-end callback helper for writing to memory mapped Message RAM
|
||||
*
|
||||
* @param base Base address of the Message RAM for the given Bosch M_CAN instance. The base address
|
||||
* must be 32-bit aligned.
|
||||
* @param offset Offset from the start of the Message RAM for the given Bosch M_CAN instance. The
|
||||
* offset must be 32-bit aligned.
|
||||
* @param src Source for the data to be written. The source address must be 32-bit aligned.
|
||||
* @param len Number of bytes to write. Must be a multiple of 4.
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO General input/output error.
|
||||
*/
|
||||
static inline int can_mcan_sys_write_mram(mem_addr_t base, uint16_t offset, const void *src,
|
||||
size_t len)
|
||||
{
|
||||
volatile uint32_t *dst32 = (volatile uint32_t *)(base + offset);
|
||||
const uint32_t *src32 = (const uint32_t *)src;
|
||||
size_t len32 = len / sizeof(uint32_t);
|
||||
|
||||
__ASSERT(base % 4U == 0U, "base must be a multiple of 4");
|
||||
__ASSERT(offset % 4U == 0U, "offset must be a multiple of 4");
|
||||
__ASSERT(POINTER_TO_UINT(src) % 4U == 0U, "src must be 32-bit aligned");
|
||||
__ASSERT(len % 4U == 0U, "len must be a multiple of 4");
|
||||
|
||||
while (len32-- > 0) {
|
||||
*dst32++ = *src32++;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
|
||||
return sys_cache_data_flush_range((void *)(base + offset), len);
|
||||
#else /* defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE) */
|
||||
return 0;
|
||||
#endif /* !defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE) */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Bosch M_CAN driver front-end callback helper for clearing memory mapped Message RAM
|
||||
*
|
||||
* Clear Message RAM by writing 0 to all words.
|
||||
*
|
||||
* @param base Base address of the Message RAM for the given Bosch M_CAN instance. The base address
|
||||
* must be 32-bit aligned.
|
||||
* @param offset Offset from the start of the Message RAM for the given Bosch M_CAN instance. The
|
||||
* offset must be 32-bit aligned.
|
||||
* @param len Number of bytes to clear. Must be a multiple of 4.
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO General input/output error.
|
||||
*/
|
||||
static inline int can_mcan_sys_clear_mram(mem_addr_t base, uint16_t offset, size_t len)
|
||||
{
|
||||
volatile uint32_t *dst32 = (volatile uint32_t *)(base + offset);
|
||||
size_t len32 = len / sizeof(uint32_t);
|
||||
|
||||
__ASSERT(base % 4U == 0U, "base must be a multiple of 4");
|
||||
__ASSERT(offset % 4U == 0U, "offset must be a multiple of 4");
|
||||
__ASSERT(len % 4U == 0U, "len must be a multiple of 4");
|
||||
|
||||
while (len32-- > 0) {
|
||||
*dst32++ = 0U;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
|
||||
return sys_cache_data_flush_range((void *)(base + offset), len);
|
||||
#else /* defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE) */
|
||||
return 0;
|
||||
#endif /* !defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE) */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read a Bosch M_CAN register
|
||||
*
|
||||
|
@ -729,6 +1062,66 @@ int can_mcan_read_reg(const struct device *dev, uint16_t reg, uint32_t *val);
|
|||
*/
|
||||
int can_mcan_write_reg(const struct device *dev, uint16_t reg, uint32_t val);
|
||||
|
||||
/**
|
||||
* @brief Read from Bosch M_CAN Message RAM
|
||||
*
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
* @param offset Offset from the start of the Message RAM for the given Bosch M_CAN instance. The
|
||||
* offset must be 32-bit aligned.
|
||||
* @param[out] dst Destination for the data read.
|
||||
* @param len Number of bytes to read. Must be a multiple of 4.
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO General input/output error.
|
||||
*/
|
||||
static inline int can_mcan_read_mram(const struct device *dev, uint16_t offset, void *dst,
|
||||
size_t len)
|
||||
{
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
|
||||
return config->ops->read_mram(dev, offset, dst, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write to Bosch M_CAN Message RAM
|
||||
*
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
* @param offset Offset from the start of the Message RAM for the given Bosch M_CAN instance. The
|
||||
* offset must be 32-bit aligned.
|
||||
* @param src Source for the data to be written
|
||||
* @param len Number of bytes to write. Must be a multiple of 4.
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO General input/output error.
|
||||
*/
|
||||
static inline int can_mcan_write_mram(const struct device *dev, uint16_t offset, const void *src,
|
||||
size_t len)
|
||||
{
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
|
||||
return config->ops->write_mram(dev, offset, src, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear Bosch M_CAN Message RAM
|
||||
*
|
||||
* Clear Message RAM by writing 0 to all words.
|
||||
*
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
* @param offset Offset from the start of the Message RAM for the given Bosch M_CAN instance. The
|
||||
* offset must be 32-bit aligned.
|
||||
* @param len Number of bytes to clear. Must be a multiple of 4.
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO General input/output error.
|
||||
*/
|
||||
static inline int can_mcan_clear_mram(const struct device *dev, uint16_t offset, size_t len)
|
||||
{
|
||||
const struct can_mcan_config *config = dev->config;
|
||||
|
||||
return config->ops->clear_mram(dev, offset, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure Bosch M_MCAN Message RAM start addresses.
|
||||
*
|
||||
|
@ -746,11 +1139,12 @@ int can_mcan_write_reg(const struct device *dev, uint16_t reg, uint32_t val);
|
|||
*
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
* @param mrba Message RAM Base Address.
|
||||
* @param mram Message RAM Address.
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO General input/output error.
|
||||
*/
|
||||
int can_mcan_configure_message_ram(const struct device *dev, uintptr_t mrba);
|
||||
int can_mcan_configure_mram(const struct device *dev, uintptr_t mrba, uintptr_t mram);
|
||||
|
||||
int can_mcan_get_capabilities(const struct device *dev, can_mode_t *cap);
|
||||
|
||||
|
|
|
@ -49,6 +49,31 @@ static int mcux_mcan_write_reg(const struct device *dev, uint16_t reg, uint32_t
|
|||
return can_mcan_sys_write_reg(mcux_config->base, reg, val);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
return can_mcan_sys_read_mram(POINTER_TO_UINT(&mcux_data->msg_ram), 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;
|
||||
|
||||
return can_mcan_sys_write_mram(POINTER_TO_UINT(&mcux_data->msg_ram), 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;
|
||||
|
||||
return can_mcan_sys_clear_mram(POINTER_TO_UINT(&mcux_data->msg_ram), offset, len);
|
||||
}
|
||||
|
||||
static int mcux_mcan_get_core_clock(const struct device *dev, uint32_t *rate)
|
||||
{
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
|
@ -88,7 +113,7 @@ static int mcux_mcan_init(const struct device *dev)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
err = can_mcan_configure_message_ram(dev, mrba);
|
||||
err = can_mcan_configure_mram(dev, mrba, POINTER_TO_UINT(&mcux_data->msg_ram));
|
||||
if (err != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -170,6 +195,14 @@ static const struct can_driver_api mcux_mcan_driver_api = {
|
|||
#endif /* CONFIG_CAN_FD_MODE */
|
||||
};
|
||||
|
||||
static const struct can_mcan_ops mcux_mcan_ops = {
|
||||
.read_reg = mcux_mcan_read_reg,
|
||||
.write_reg = mcux_mcan_write_reg,
|
||||
.read_mram = mcux_mcan_read_mram,
|
||||
.write_mram = mcux_mcan_write_mram,
|
||||
.clear_mram = mcux_mcan_clear_mram,
|
||||
};
|
||||
|
||||
#define MCUX_MCAN_INIT(n) \
|
||||
PINCTRL_DT_INST_DEFINE(n); \
|
||||
\
|
||||
|
@ -186,14 +219,12 @@ static const struct can_driver_api mcux_mcan_driver_api = {
|
|||
\
|
||||
static const struct can_mcan_config can_mcan_config_##n = \
|
||||
CAN_MCAN_DT_CONFIG_INST_GET(n, &mcux_mcan_config_##n, \
|
||||
mcux_mcan_read_reg, \
|
||||
mcux_mcan_write_reg); \
|
||||
&mcux_mcan_ops); \
|
||||
\
|
||||
static struct mcux_mcan_data mcux_mcan_data_##n; \
|
||||
\
|
||||
static struct can_mcan_data can_mcan_data_##n = \
|
||||
CAN_MCAN_DATA_INITIALIZER(&mcux_mcan_data_##n.msg_ram, \
|
||||
&mcux_mcan_data_##n); \
|
||||
CAN_MCAN_DATA_INITIALIZER(&mcux_mcan_data_##n); \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(n, &mcux_mcan_init, NULL, \
|
||||
&can_mcan_data_##n, \
|
||||
|
|
|
@ -47,6 +47,31 @@ static int can_sam_write_reg(const struct device *dev, uint16_t reg, uint32_t va
|
|||
return can_mcan_sys_write_reg(sam_config->base, reg, val);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
return can_mcan_sys_read_mram(POINTER_TO_UINT(&sam_data->msg_ram), 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;
|
||||
|
||||
return can_mcan_sys_write_mram(POINTER_TO_UINT(&sam_data->msg_ram), 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;
|
||||
|
||||
return can_mcan_sys_clear_mram(POINTER_TO_UINT(&sam_data->msg_ram), offset, len);
|
||||
}
|
||||
|
||||
static int can_sam_get_core_clock(const struct device *dev, uint32_t *rate)
|
||||
{
|
||||
const struct can_mcan_config *mcan_cfg = dev->config;
|
||||
|
@ -71,6 +96,8 @@ 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);
|
||||
|
@ -80,7 +107,7 @@ static int can_sam_init(const struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = can_mcan_configure_message_ram(dev, 0U);
|
||||
ret = can_mcan_configure_mram(dev, 0U, POINTER_TO_UINT(&sam_data->msg_ram));
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -145,6 +172,14 @@ static const struct can_driver_api can_sam_driver_api = {
|
|||
#endif /* CONFIG_CAN_FD_MODE */
|
||||
};
|
||||
|
||||
static const struct can_mcan_ops can_sam_ops = {
|
||||
.read_reg = can_sam_read_reg,
|
||||
.write_reg = can_sam_write_reg,
|
||||
.read_mram = can_sam_read_mram,
|
||||
.write_mram = can_sam_write_mram,
|
||||
.clear_mram = can_sam_clear_mram,
|
||||
};
|
||||
|
||||
#define CAN_SAM_IRQ_CFG_FUNCTION(inst) \
|
||||
static void config_can_##inst##_irq(void) \
|
||||
{ \
|
||||
|
@ -170,15 +205,13 @@ 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_read_reg, \
|
||||
can_sam_write_reg);
|
||||
&can_sam_ops);
|
||||
|
||||
#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.msg_ram, \
|
||||
&can_sam_data_##inst); \
|
||||
CAN_MCAN_DATA_INITIALIZER(&can_sam_data_##inst);
|
||||
|
||||
#define CAN_SAM_DEVICE_INST(inst) \
|
||||
DEVICE_DT_INST_DEFINE(inst, &can_sam_init, NULL, \
|
||||
|
|
|
@ -63,6 +63,31 @@ static int can_sam0_write_reg(const struct device *dev, uint16_t reg, uint32_t v
|
|||
return can_mcan_sys_write_reg(sam_config->base, reg, val);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
return can_mcan_sys_read_mram(POINTER_TO_UINT(&sam_data->msg_ram), 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;
|
||||
|
||||
return can_mcan_sys_write_mram(POINTER_TO_UINT(&sam_data->msg_ram), 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;
|
||||
|
||||
return can_mcan_sys_clear_mram(POINTER_TO_UINT(&sam_data->msg_ram), offset, len);
|
||||
}
|
||||
|
||||
void can_sam0_line_x_isr(const struct device *dev)
|
||||
{
|
||||
can_mcan_line_0_isr(dev);
|
||||
|
@ -98,6 +123,8 @@ 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);
|
||||
|
@ -108,7 +135,7 @@ static int can_sam0_init(const struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = can_mcan_configure_message_ram(dev, 0U);
|
||||
ret = can_mcan_configure_mram(dev, 0U, POINTER_TO_UINT(&sam_data->msg_ram));
|
||||
if (ret != 0) {
|
||||
LOG_ERR("failed to configure message ram");
|
||||
return ret;
|
||||
|
@ -175,6 +202,14 @@ static const struct can_driver_api can_sam0_driver_api = {
|
|||
#endif /* CONFIG_CAN_FD_MODE */
|
||||
};
|
||||
|
||||
static const struct can_mcan_ops can_sam0_ops = {
|
||||
.read_reg = can_sam0_read_reg,
|
||||
.write_reg = can_sam0_write_reg,
|
||||
.read_mram = can_sam0_read_mram,
|
||||
.write_mram = can_sam0_write_mram,
|
||||
.clear_mram = can_sam0_clear_mram,
|
||||
};
|
||||
|
||||
#define CAN_SAM0_IRQ_CFG_FUNCTION(inst) \
|
||||
static void config_can_##inst##_irq(void) \
|
||||
{ \
|
||||
|
@ -197,16 +232,13 @@ 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_read_reg, \
|
||||
can_sam0_write_reg);
|
||||
CAN_MCAN_DT_CONFIG_INST_GET(inst, &can_sam0_cfg_##inst, &can_sam0_ops);
|
||||
|
||||
#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.msg_ram, \
|
||||
&can_sam0_data_##inst); \
|
||||
CAN_MCAN_DATA_INITIALIZER(&can_sam0_data_##inst);
|
||||
|
||||
#define CAN_SAM0_DEVICE_INST(inst) \
|
||||
DEVICE_DT_INST_DEFINE(inst, &can_sam0_init, NULL, \
|
||||
|
|
|
@ -169,6 +169,7 @@ LOG_MODULE_REGISTER(can_stm32fd, CONFIG_CAN_LOG_LEVEL);
|
|||
|
||||
struct can_stm32fd_config {
|
||||
mm_reg_t base;
|
||||
mem_addr_t mram;
|
||||
size_t pclk_len;
|
||||
const struct stm32_pclken *pclken;
|
||||
void (*config_irq)(void);
|
||||
|
@ -445,6 +446,31 @@ static int can_stm32fd_write_reg(const struct device *dev, uint16_t reg, uint32_
|
|||
return can_mcan_sys_write_reg(stm32fd_config->base, remap, bits);
|
||||
}
|
||||
|
||||
static int can_stm32fd_read_mram(const struct device *dev, uint16_t offset, void *dst, size_t len)
|
||||
{
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
const struct can_stm32fd_config *stm32fd_config = mcan_config->custom;
|
||||
|
||||
return can_mcan_sys_read_mram(stm32fd_config->mram, offset, dst, len);
|
||||
}
|
||||
|
||||
static int can_stm32fd_write_mram(const struct device *dev, uint16_t offset, const void *src,
|
||||
size_t len)
|
||||
{
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
const struct can_stm32fd_config *stm32fd_config = mcan_config->custom;
|
||||
|
||||
return can_mcan_sys_write_mram(stm32fd_config->mram, offset, src, len);
|
||||
}
|
||||
|
||||
static int can_stm32fd_clear_mram(const struct device *dev, uint16_t offset, size_t len)
|
||||
{
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
const struct can_stm32fd_config *stm32fd_config = mcan_config->custom;
|
||||
|
||||
return can_mcan_sys_clear_mram(stm32fd_config->mram, offset, len);
|
||||
}
|
||||
|
||||
static int can_stm32fd_get_core_clock(const struct device *dev, uint32_t *rate)
|
||||
{
|
||||
const uint32_t rate_tmp = LL_RCC_GetFDCANClockFreq(LL_RCC_FDCAN_CLKSOURCE);
|
||||
|
@ -601,12 +627,21 @@ static const struct can_driver_api can_stm32fd_driver_api = {
|
|||
#endif /* CONFIG_CAN_FD_MODE */
|
||||
};
|
||||
|
||||
static const struct can_mcan_ops can_stm32fd_ops = {
|
||||
.read_reg = can_stm32fd_read_reg,
|
||||
.write_reg = can_stm32fd_write_reg,
|
||||
.read_mram = can_stm32fd_read_mram,
|
||||
.write_mram = can_stm32fd_write_mram,
|
||||
.clear_mram = can_stm32fd_clear_mram,
|
||||
};
|
||||
|
||||
/* Assert that the Message RAM configuration meets the hardware limitiations */
|
||||
BUILD_ASSERT(NUM_STD_FILTER_ELEMENTS <= 28, "Maximum standard filter elements exceeded");
|
||||
BUILD_ASSERT(NUM_EXT_FILTER_ELEMENTS <= 8, "Maximum extended filter elements exceeded");
|
||||
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_IRQ_CFG_FUNCTION(inst) \
|
||||
|
@ -630,6 +665,7 @@ static void config_can_##inst##_irq(void) \
|
|||
\
|
||||
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), \
|
||||
.pclken = can_stm32fd_pclken_##inst, \
|
||||
.pclk_len = DT_INST_NUM_CLOCKS(inst), \
|
||||
.config_irq = config_can_##inst##_irq, \
|
||||
|
@ -639,14 +675,11 @@ 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_read_reg, \
|
||||
can_stm32fd_write_reg);
|
||||
&can_stm32fd_ops);
|
||||
|
||||
#define CAN_STM32FD_DATA_INST(inst) \
|
||||
static struct can_mcan_data can_mcan_data_##inst = \
|
||||
CAN_MCAN_DATA_INITIALIZER((struct can_mcan_msg_sram *) \
|
||||
DT_INST_REG_ADDR_BY_NAME(inst, message_ram), \
|
||||
NULL);
|
||||
CAN_MCAN_DATA_INITIALIZER(NULL);
|
||||
|
||||
#define CAN_STM32FD_DEVICE_INST(inst) \
|
||||
DEVICE_DT_INST_DEFINE(inst, &can_stm32fd_init, NULL, \
|
||||
|
|
|
@ -22,6 +22,7 @@ LOG_MODULE_REGISTER(can_stm32h7, CONFIG_CAN_LOG_LEVEL);
|
|||
|
||||
struct can_stm32h7_config {
|
||||
mm_reg_t base;
|
||||
mem_addr_t mram;
|
||||
void (*config_irq)(void);
|
||||
const struct pinctrl_dev_config *pcfg;
|
||||
struct stm32_pclken pclken;
|
||||
|
@ -29,18 +30,43 @@ struct can_stm32h7_config {
|
|||
|
||||
static int can_stm32h7_read_reg(const struct device *dev, uint16_t reg, uint32_t *val)
|
||||
{
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
const struct can_stm32h7_config *stm32h7_config = mcan_config->custom;
|
||||
const struct can_mcan_config *mcan_cfg = dev->config;
|
||||
const struct can_stm32h7_config *stm32h7_cfg = mcan_cfg->custom;
|
||||
|
||||
return can_mcan_sys_read_reg(stm32h7_config->base, reg, val);
|
||||
return can_mcan_sys_read_reg(stm32h7_cfg->base, reg, val);
|
||||
}
|
||||
|
||||
static int can_stm32h7_write_reg(const struct device *dev, uint16_t reg, uint32_t val)
|
||||
{
|
||||
const struct can_mcan_config *mcan_config = dev->config;
|
||||
const struct can_stm32h7_config *stm32h7_config = mcan_config->custom;
|
||||
const struct can_mcan_config *mcan_cfg = dev->config;
|
||||
const struct can_stm32h7_config *stm32h7_cfg = mcan_cfg->custom;
|
||||
|
||||
return can_mcan_sys_write_reg(stm32h7_config->base, reg, val);
|
||||
return can_mcan_sys_write_reg(stm32h7_cfg->base, reg, val);
|
||||
}
|
||||
|
||||
static int can_stm32h7_read_mram(const struct device *dev, uint16_t offset, void *dst, size_t len)
|
||||
{
|
||||
const struct can_mcan_config *mcan_cfg = dev->config;
|
||||
const struct can_stm32h7_config *stm32h7_cfg = mcan_cfg->custom;
|
||||
|
||||
return can_mcan_sys_read_mram(stm32h7_cfg->mram, offset, dst, len);
|
||||
}
|
||||
|
||||
static int can_stm32h7_write_mram(const struct device *dev, uint16_t offset, const void *src,
|
||||
size_t len)
|
||||
{
|
||||
const struct can_mcan_config *mcan_cfg = dev->config;
|
||||
const struct can_stm32h7_config *stm32h7_cfg = mcan_cfg->custom;
|
||||
|
||||
return can_mcan_sys_write_mram(stm32h7_cfg->mram, offset, src, len);
|
||||
}
|
||||
|
||||
static int can_stm32h7_clear_mram(const struct device *dev, uint16_t offset, size_t len)
|
||||
{
|
||||
const struct can_mcan_config *mcan_cfg = dev->config;
|
||||
const struct can_stm32h7_config *stm32h7_cfg = mcan_cfg->custom;
|
||||
|
||||
return can_mcan_sys_clear_mram(stm32h7_cfg->mram, offset, len);
|
||||
}
|
||||
|
||||
static int can_stm32h7_get_core_clock(const struct device *dev, uint32_t *rate)
|
||||
|
@ -93,8 +119,6 @@ static int can_stm32h7_init(const struct device *dev)
|
|||
{
|
||||
const struct can_mcan_config *mcan_cfg = dev->config;
|
||||
const struct can_stm32h7_config *stm32h7_cfg = mcan_cfg->custom;
|
||||
struct can_mcan_data *mcan_data = dev->data;
|
||||
const uintptr_t mrba = POINTER_TO_UINT(mcan_data->msg_ram);
|
||||
int ret;
|
||||
|
||||
/* Configure dt provided device signals when available */
|
||||
|
@ -109,7 +133,7 @@ static int can_stm32h7_init(const struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = can_mcan_configure_message_ram(dev, mrba);
|
||||
ret = can_mcan_configure_mram(dev, stm32h7_cfg->mram, stm32h7_cfg->mram);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -182,6 +206,14 @@ static const struct can_driver_api can_stm32h7_driver_api = {
|
|||
#endif
|
||||
};
|
||||
|
||||
static const struct can_mcan_ops can_stm32h7_ops = {
|
||||
.read_reg = can_stm32h7_read_reg,
|
||||
.write_reg = can_stm32h7_write_reg,
|
||||
.read_mram = can_stm32h7_read_mram,
|
||||
.write_mram = can_stm32h7_write_mram,
|
||||
.clear_mram = can_stm32h7_clear_mram,
|
||||
};
|
||||
|
||||
#define CAN_STM32H7_MCAN_INIT(n) \
|
||||
static void stm32h7_mcan_irq_config_##n(void); \
|
||||
\
|
||||
|
@ -189,6 +221,7 @@ static const struct can_driver_api can_stm32h7_driver_api = {
|
|||
\
|
||||
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), \
|
||||
.config_irq = stm32h7_mcan_irq_config_##n, \
|
||||
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
|
||||
.pclken = { \
|
||||
|
@ -199,12 +232,10 @@ static const struct can_driver_api can_stm32h7_driver_api = {
|
|||
\
|
||||
static const struct can_mcan_config can_mcan_cfg_##n = \
|
||||
CAN_MCAN_DT_CONFIG_INST_GET(n, &can_stm32h7_cfg_##n, \
|
||||
can_stm32h7_read_reg, \
|
||||
can_stm32h7_write_reg); \
|
||||
&can_stm32h7_ops); \
|
||||
\
|
||||
static struct can_mcan_data can_mcan_data_##n = \
|
||||
CAN_MCAN_DATA_INITIALIZER((struct can_mcan_msg_sram *) \
|
||||
DT_INST_REG_ADDR_BY_NAME(n, message_ram), NULL); \
|
||||
CAN_MCAN_DATA_INITIALIZER(NULL); \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(n, &can_stm32h7_init, NULL, \
|
||||
&can_mcan_data_##n, \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue