drivers: can: mcan: move message RAM configuration to front-end drivers
Some Bosch M_CAN IP core implementations use a fixed Message RAM configuration, other use a fixed memory area and relative addressing, others again have custom registers for configuring the Message RAM. Move the responsibility for configuring the various Bosch M_CAN Message RAM addresses to the front-end drivers. This removes some of the front-end specific code from the backend. Provide a helper function for configuring the most common variations. Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
parent
65350b8362
commit
a781ccde0f
6 changed files with 123 additions and 72 deletions
|
@ -1200,71 +1200,16 @@ unlock:
|
|||
k_mutex_unlock(&data->lock);
|
||||
}
|
||||
|
||||
int can_mcan_init(const struct device *dev)
|
||||
#ifndef CONFIG_CAN_STM32FD
|
||||
int can_mcan_configure_message_ram(const struct device *dev, uintptr_t mrba)
|
||||
{
|
||||
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;
|
||||
#endif /* CONFIG_CAN_FD_MODE */
|
||||
uint32_t reg;
|
||||
int err;
|
||||
|
||||
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);
|
||||
|
||||
if (config->phy != NULL) {
|
||||
if (!device_is_ready(config->phy)) {
|
||||
LOG_ERR("CAN transceiver not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
err = can_mcan_exit_sleep_mode(dev);
|
||||
if (err != 0) {
|
||||
LOG_ERR("Failed to exit sleep mode");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
err = can_mcan_enter_init_mode(dev, K_MSEC(CAN_INIT_TIMEOUT_MS));
|
||||
if (err != 0) {
|
||||
LOG_ERR("Failed to enter init mode");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
can_mcan_enable_configuration_change(dev);
|
||||
|
||||
#if CONFIG_CAN_LOG_LEVEL >= LOG_LEVEL_DBG
|
||||
err = can_mcan_read_reg(dev, CAN_MCAN_CREL, ®);
|
||||
if (err != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
LOG_DBG("IP rel: %lu.%lu.%lu %02lu.%lu.%lu", FIELD_GET(CAN_MCAN_CREL_REL, reg),
|
||||
FIELD_GET(CAN_MCAN_CREL_STEP, reg), FIELD_GET(CAN_MCAN_CREL_SUBSTEP, reg),
|
||||
FIELD_GET(CAN_MCAN_CREL_YEAR, reg), FIELD_GET(CAN_MCAN_CREL_MON, reg),
|
||||
FIELD_GET(CAN_MCAN_CREL_DAY, reg));
|
||||
#endif /* CONFIG_CAN_LOG_LEVEL >= LOG_LEVEL_DBG */
|
||||
|
||||
#ifndef CONFIG_CAN_STM32FD
|
||||
uintptr_t mrba = 0U;
|
||||
|
||||
#ifdef CONFIG_CAN_STM32H7
|
||||
mrba = POINTER_TO_UINT(msg_ram);
|
||||
#endif /* CONFIG_CAN_STM32H7 */
|
||||
|
||||
#ifdef CONFIG_CAN_MCUX_MCAN
|
||||
mrba = POINTER_TO_UINT(msg_ram) & CAN_MCAN_MRBA_BA;
|
||||
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_MRBA, mrba);
|
||||
if (err != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
#endif /* CONFIG_CAN_MCUX_MCAN */
|
||||
|
||||
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));
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_SIDFC, reg);
|
||||
|
@ -1342,7 +1287,59 @@ int can_mcan_init(const struct device *dev)
|
|||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* !CONFIG_CAN_STM32FD */
|
||||
|
||||
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;
|
||||
#endif /* CONFIG_CAN_FD_MODE */
|
||||
uint32_t reg;
|
||||
int err;
|
||||
|
||||
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);
|
||||
|
||||
if (config->phy != NULL) {
|
||||
if (!device_is_ready(config->phy)) {
|
||||
LOG_ERR("CAN transceiver not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
err = can_mcan_exit_sleep_mode(dev);
|
||||
if (err != 0) {
|
||||
LOG_ERR("Failed to exit sleep mode");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
err = can_mcan_enter_init_mode(dev, K_MSEC(CAN_INIT_TIMEOUT_MS));
|
||||
if (err != 0) {
|
||||
LOG_ERR("Failed to enter init mode");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
can_mcan_enable_configuration_change(dev);
|
||||
|
||||
#if CONFIG_CAN_LOG_LEVEL >= LOG_LEVEL_DBG
|
||||
err = can_mcan_read_reg(dev, CAN_MCAN_CREL, ®);
|
||||
if (err != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
LOG_DBG("IP rel: %lu.%lu.%lu %02lu.%lu.%lu", FIELD_GET(CAN_MCAN_CREL_REL, reg),
|
||||
FIELD_GET(CAN_MCAN_CREL_STEP, reg), FIELD_GET(CAN_MCAN_CREL_SUBSTEP, reg),
|
||||
FIELD_GET(CAN_MCAN_CREL_YEAR, reg), FIELD_GET(CAN_MCAN_CREL_MON, reg),
|
||||
FIELD_GET(CAN_MCAN_CREL_DAY, reg));
|
||||
#endif /* CONFIG_CAN_LOG_LEVEL >= LOG_LEVEL_DBG */
|
||||
|
||||
err = can_mcan_read_reg(dev, CAN_MCAN_CCCR, ®);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
|
@ -1394,21 +1391,7 @@ int can_mcan_init(const struct device *dev)
|
|||
}
|
||||
#endif /* defined(CONFIG_CAN_DELAY_COMP) && defined(CONFIG_CAN_FD_MODE) */
|
||||
|
||||
#ifdef CONFIG_CAN_STM32FD
|
||||
err = can_mcan_read_reg(dev, CAN_MCAN_RXGFC, ®);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
reg |= FIELD_PREP(CAN_MCAN_RXGFC_LSS, CONFIG_CAN_MAX_STD_ID_FILTER) |
|
||||
FIELD_PREP(CAN_MCAN_RXGFC_LSE, CONFIG_CAN_MAX_EXT_ID_FILTER) |
|
||||
FIELD_PREP(CAN_MCAN_RXGFC_ANFS, 0x2) | FIELD_PREP(CAN_MCAN_RXGFC_ANFE, 0x2);
|
||||
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_RXGFC, reg);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
#else /* CONFIG_CAN_STM32FD*/
|
||||
#ifndef CONFIG_CAN_STM32FD
|
||||
err = can_mcan_read_reg(dev, CAN_MCAN_GFC, ®);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
|
|
|
@ -941,6 +941,31 @@ 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 Configure Bosch M_MCAN Message RAM start addresses.
|
||||
*
|
||||
* Bosch M_CAN driver front-end callback helper function for configuring the start addresses of the
|
||||
* Bosch M_CAN Rx FIFO0 (RXFOC), Rx FIFO1 (RXF1C), Rx Buffer (RXBCC), Tx Buffer (TXBC), and Tx Event
|
||||
* FIFO (TXEFC) in Message RAM.
|
||||
*
|
||||
* The start addresses (containing bits 15:2 since Bosch M_CAN message RAM is accessed as 32 bit
|
||||
* words) are calculated relative to the provided Message RAM Base Address (mrba).
|
||||
*
|
||||
* Some Bosch M_CAN implementations use a fixed Message RAM configuration, other use a fixed memory
|
||||
* area and relative addressing, others again have custom registers for configuring the Message
|
||||
* RAM. It is the responsibility of the front-end driver to call this function during driver
|
||||
* initialization as needed.
|
||||
*
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
* @param mrba Message RAM Base Address.
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO General input/output error.
|
||||
*/
|
||||
#ifndef CONFIG_CAN_STM32FD
|
||||
int can_mcan_configure_message_ram(const struct device *dev, uintptr_t mrba);
|
||||
#endif /* !CONFIG_CAN_STM32FD */
|
||||
|
||||
int can_mcan_get_capabilities(const struct device *dev, can_mode_t *cap);
|
||||
|
||||
int can_mcan_start(const struct device *dev);
|
||||
|
|
|
@ -58,6 +58,9 @@ 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) & CAN_MCAN_MRBA_BA;
|
||||
int err;
|
||||
|
||||
if (!device_is_ready(mcux_config->clock_dev)) {
|
||||
|
@ -76,6 +79,16 @@ static int mcux_mcan_init(const struct device *dev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = can_mcan_write_reg(dev, CAN_MCAN_MRBA, (uint32_t)mrba);
|
||||
if (err != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
err = can_mcan_configure_message_ram(dev, mrba);
|
||||
if (err != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
err = can_mcan_init(dev);
|
||||
if (err) {
|
||||
LOG_ERR("failed to initialize mcan (err %d)", err);
|
||||
|
|
|
@ -80,6 +80,11 @@ static int can_sam_init(const struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = can_mcan_configure_message_ram(dev, 0U);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = can_mcan_init(dev);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
|
|
|
@ -112,6 +112,7 @@ static int can_stm32fd_init(const struct device *dev)
|
|||
{
|
||||
const struct can_mcan_config *mcan_cfg = dev->config;
|
||||
const struct can_stm32fd_config *stm32fd_cfg = mcan_cfg->custom;
|
||||
uint32_t rxgfc;
|
||||
int ret;
|
||||
|
||||
/* Configure dt provided device signals when available */
|
||||
|
@ -127,6 +128,23 @@ static int can_stm32fd_init(const struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
can_mcan_enable_configuration_change(dev);
|
||||
|
||||
/* Setup STM32 FDCAN Global Filter Configuration Register */
|
||||
ret = can_mcan_read_reg(dev, CAN_MCAN_RXGFC, &rxgfc);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
rxgfc |= FIELD_PREP(CAN_MCAN_RXGFC_LSS, CONFIG_CAN_MAX_STD_ID_FILTER) |
|
||||
FIELD_PREP(CAN_MCAN_RXGFC_LSE, CONFIG_CAN_MAX_EXT_ID_FILTER) |
|
||||
FIELD_PREP(CAN_MCAN_RXGFC_ANFS, 0x2) | FIELD_PREP(CAN_MCAN_RXGFC_ANFE, 0x2);
|
||||
|
||||
ret = can_mcan_write_reg(dev, CAN_MCAN_RXGFC, rxgfc);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = can_mcan_init(dev);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
|
|
|
@ -93,6 +93,8 @@ 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 */
|
||||
|
@ -107,6 +109,11 @@ static int can_stm32h7_init(const struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = can_mcan_configure_message_ram(dev, mrba);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = can_mcan_init(dev);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue