drivers: can: mcan: let front-end drivers supply register r/w functions
Let the Bosch M_CAN front-end drivers supply their own register read/write functions. This is preparation for handling non-standard Bosch M_CAN register layouts directly in the front-end 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
1c0a43ec45
commit
bbfc1f905c
10 changed files with 197 additions and 35 deletions
|
@ -47,26 +47,34 @@ static void memset32_volatile(volatile void *dst_, uint32_t val, size_t len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int can_mcan_write_reg(const struct device *dev, uint16_t reg, uint32_t val)
|
|
||||||
{
|
|
||||||
const struct can_mcan_config *config = dev->config;
|
|
||||||
mm_reg_t base = config->base;
|
|
||||||
|
|
||||||
LOG_DBG("write reg 0x%03x = 0x%08x", reg, val);
|
|
||||||
sys_write32(val, base + reg);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int can_mcan_read_reg(const struct device *dev, uint16_t reg, uint32_t *val)
|
static inline int can_mcan_read_reg(const struct device *dev, uint16_t reg, uint32_t *val)
|
||||||
{
|
{
|
||||||
const struct can_mcan_config *config = dev->config;
|
const struct can_mcan_config *config = dev->config;
|
||||||
mm_reg_t base = config->base;
|
int err;
|
||||||
|
|
||||||
*val = sys_read32(base + reg);
|
err = config->read_reg(dev, reg, val);
|
||||||
LOG_DBG("read reg 0x%03x = 0x%08x", reg, *val);
|
if (err != 0) {
|
||||||
|
LOG_ERR("failed to read reg 0x%03x (err %d)", reg, err);
|
||||||
|
} else {
|
||||||
|
LOG_DBG("read reg 0x%03x = 0x%08x", reg, *val);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline 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);
|
||||||
|
if (err != 0) {
|
||||||
|
LOG_ERR("failed to write reg 0x%03x (err %d)", reg, err);
|
||||||
|
} else {
|
||||||
|
LOG_DBG("write reg 0x%03x = 0x%08x", reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int can_mcan_exit_sleep_mode(const struct device *dev)
|
static int can_mcan_exit_sleep_mode(const struct device *dev)
|
||||||
|
|
|
@ -190,8 +190,33 @@ struct can_mcan_data {
|
||||||
void *custom;
|
void *custom;
|
||||||
} __aligned(4);
|
} __aligned(4);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bosch M_CAN driver front-end callback for reading a register value
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param reg Register offset
|
||||||
|
* @param[out] val Register value
|
||||||
|
*
|
||||||
|
* @retval 0 If successful.
|
||||||
|
* @retval -EIO General input/output error.
|
||||||
|
*/
|
||||||
|
typedef int (*can_mcan_read_reg_t)(const struct device *dev, uint16_t reg, uint32_t *val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bosch M_CAN driver front-end callback for writing a register value
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param reg Register offset
|
||||||
|
* @param val Register value
|
||||||
|
*
|
||||||
|
* @retval 0 If successful.
|
||||||
|
* @retval -EIO General input/output error.
|
||||||
|
*/
|
||||||
|
typedef int (*can_mcan_write_reg_t)(const struct device *dev, uint16_t reg, uint32_t val);
|
||||||
|
|
||||||
struct can_mcan_config {
|
struct can_mcan_config {
|
||||||
mm_reg_t base;
|
can_mcan_read_reg_t read_reg;
|
||||||
|
can_mcan_write_reg_t write_reg;
|
||||||
uint32_t bus_speed;
|
uint32_t bus_speed;
|
||||||
uint32_t bus_speed_data;
|
uint32_t bus_speed_data;
|
||||||
uint16_t sjw;
|
uint16_t sjw;
|
||||||
|
@ -210,10 +235,18 @@ struct can_mcan_config {
|
||||||
const void *custom;
|
const void *custom;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 _read_reg Driver frontend Bosch M_CAN register read function
|
||||||
|
* @param _write_reg Driver frontend Bosch M_CAN register write function
|
||||||
|
*/
|
||||||
#ifdef CONFIG_CAN_FD_MODE
|
#ifdef CONFIG_CAN_FD_MODE
|
||||||
#define CAN_MCAN_DT_CONFIG_GET(node_id, _custom_config) \
|
#define CAN_MCAN_DT_CONFIG_GET(node_id, _custom, _read_reg, _write_reg) \
|
||||||
{ \
|
{ \
|
||||||
.base = (mm_reg_t)DT_REG_ADDR_BY_NAME(node_id, m_can), \
|
.read_reg = _read_reg, .write_reg = _write_reg, \
|
||||||
.bus_speed = DT_PROP(node_id, bus_speed), .sjw = DT_PROP(node_id, sjw), \
|
.bus_speed = DT_PROP(node_id, bus_speed), .sjw = DT_PROP(node_id, sjw), \
|
||||||
.sample_point = DT_PROP_OR(node_id, sample_point, 0), \
|
.sample_point = DT_PROP_OR(node_id, sample_point, 0), \
|
||||||
.prop_ts1 = DT_PROP_OR(node_id, prop_seg, 0) + DT_PROP_OR(node_id, phase_seg1, 0), \
|
.prop_ts1 = DT_PROP_OR(node_id, prop_seg, 0) + DT_PROP_OR(node_id, phase_seg1, 0), \
|
||||||
|
@ -227,30 +260,76 @@ struct can_mcan_config {
|
||||||
.tx_delay_comp_offset = DT_PROP(node_id, tx_delay_comp_offset), \
|
.tx_delay_comp_offset = DT_PROP(node_id, tx_delay_comp_offset), \
|
||||||
.phy = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(node_id, phys)), \
|
.phy = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(node_id, phys)), \
|
||||||
.max_bitrate = DT_CAN_TRANSCEIVER_MAX_BITRATE(node_id, 8000000), \
|
.max_bitrate = DT_CAN_TRANSCEIVER_MAX_BITRATE(node_id, 8000000), \
|
||||||
.custom = _custom_config, \
|
.custom = _custom, \
|
||||||
}
|
}
|
||||||
#else /* CONFIG_CAN_FD_MODE */
|
#else /* CONFIG_CAN_FD_MODE */
|
||||||
#define CAN_MCAN_DT_CONFIG_GET(node_id, _custom_config) \
|
#define CAN_MCAN_DT_CONFIG_GET(node_id, _custom, _read_reg, _write_reg) \
|
||||||
{ \
|
{ \
|
||||||
.base = (mm_reg_t)DT_REG_ADDR_BY_NAME(node_id, m_can), \
|
.read_reg = _read_reg, .write_reg = _write_reg, \
|
||||||
.bus_speed = DT_PROP(node_id, bus_speed), .sjw = DT_PROP(node_id, sjw), \
|
.bus_speed = DT_PROP(node_id, bus_speed), .sjw = DT_PROP(node_id, sjw), \
|
||||||
.sample_point = DT_PROP_OR(node_id, sample_point, 0), \
|
.sample_point = DT_PROP_OR(node_id, sample_point, 0), \
|
||||||
.prop_ts1 = DT_PROP_OR(node_id, prop_seg, 0) + DT_PROP_OR(node_id, phase_seg1, 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), \
|
.ts2 = DT_PROP_OR(node_id, phase_seg2, 0), \
|
||||||
.phy = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(node_id, phys)), \
|
.phy = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(node_id, phys)), \
|
||||||
.max_bitrate = DT_CAN_TRANSCEIVER_MAX_BITRATE(node_id, 1000000), \
|
.max_bitrate = DT_CAN_TRANSCEIVER_MAX_BITRATE(node_id, 1000000), \
|
||||||
.custom = _custom_config, \
|
.custom = _custom, \
|
||||||
}
|
}
|
||||||
#endif /* !CONFIG_CAN_FD_MODE */
|
#endif /* !CONFIG_CAN_FD_MODE */
|
||||||
|
|
||||||
#define CAN_MCAN_DT_CONFIG_INST_GET(inst, _custom_config) \
|
/**
|
||||||
CAN_MCAN_DT_CONFIG_GET(DT_DRV_INST(inst), _custom_config)
|
* @brief Static initializer for @p can_mcan_config struct from DT_DRV_COMPAT instance
|
||||||
|
*
|
||||||
|
* @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
|
||||||
|
* @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_DATA_INITIALIZER(_msg_ram, _custom_data) \
|
/**
|
||||||
|
* @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) \
|
||||||
{ \
|
{ \
|
||||||
.msg_ram = _msg_ram, .custom = _custom_data, \
|
.msg_ram = _msg_ram, .custom = _custom, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bosch M_CAN driver front-end callback helper for reading a memory mapped register
|
||||||
|
*
|
||||||
|
* @param base Register base address
|
||||||
|
* @param reg Register offset
|
||||||
|
* @param[out] val Register value
|
||||||
|
*
|
||||||
|
* @retval 0 Memory mapped register read always succeeds.
|
||||||
|
*/
|
||||||
|
static inline int can_mcan_sys_read_reg(mm_reg_t base, uint16_t reg, uint32_t *val)
|
||||||
|
{
|
||||||
|
*val = sys_read32(base + reg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bosch M_CAN driver front-end callback helper for writing a memory mapped register
|
||||||
|
*
|
||||||
|
* @param base Register base address
|
||||||
|
* @param reg Register offset
|
||||||
|
* @param val Register value
|
||||||
|
*
|
||||||
|
* @retval 0 Memory mapped register write always succeeds.
|
||||||
|
*/
|
||||||
|
static inline int can_mcan_sys_write_reg(mm_reg_t base, uint16_t reg, uint32_t val)
|
||||||
|
{
|
||||||
|
sys_write32(val, base + reg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int can_mcan_get_capabilities(const struct device *dev, can_mode_t *cap);
|
int can_mcan_get_capabilities(const struct device *dev, can_mode_t *cap);
|
||||||
|
|
||||||
int can_mcan_start(const struct device *dev);
|
int can_mcan_start(const struct device *dev);
|
||||||
|
|
|
@ -18,6 +18,7 @@ LOG_MODULE_REGISTER(can_mcux_mcan, CONFIG_CAN_LOG_LEVEL);
|
||||||
#define DT_DRV_COMPAT nxp_lpc_mcan
|
#define DT_DRV_COMPAT nxp_lpc_mcan
|
||||||
|
|
||||||
struct mcux_mcan_config {
|
struct mcux_mcan_config {
|
||||||
|
mm_reg_t base;
|
||||||
const struct device *clock_dev;
|
const struct device *clock_dev;
|
||||||
clock_control_subsys_t clock_subsys;
|
clock_control_subsys_t clock_subsys;
|
||||||
void (*irq_config_func)(const struct device *dev);
|
void (*irq_config_func)(const struct device *dev);
|
||||||
|
@ -28,6 +29,22 @@ struct mcux_mcan_data {
|
||||||
struct can_mcan_msg_sram msg_ram __nocache;
|
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;
|
||||||
|
const struct mcux_mcan_config *mcux_config = mcan_config->custom;
|
||||||
|
|
||||||
|
return can_mcan_sys_read_reg(mcux_config->base, reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mcux_mcan_write_reg(const struct device *dev, uint16_t reg, uint32_t val)
|
||||||
|
{
|
||||||
|
const struct can_mcan_config *mcan_config = dev->config;
|
||||||
|
const struct mcux_mcan_config *mcux_config = mcan_config->custom;
|
||||||
|
|
||||||
|
return can_mcan_sys_write_reg(mcux_config->base, reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
static int mcux_mcan_get_core_clock(const struct device *dev, uint32_t *rate)
|
static int mcux_mcan_get_core_clock(const struct device *dev, uint32_t *rate)
|
||||||
{
|
{
|
||||||
const struct can_mcan_config *mcan_config = dev->config;
|
const struct can_mcan_config *mcan_config = dev->config;
|
||||||
|
@ -142,6 +159,7 @@ static const struct can_driver_api mcux_mcan_driver_api = {
|
||||||
static void mcux_mcan_irq_config_##n(const struct device *dev); \
|
static void mcux_mcan_irq_config_##n(const struct device *dev); \
|
||||||
\
|
\
|
||||||
static const struct mcux_mcan_config mcux_mcan_config_##n = { \
|
static const struct mcux_mcan_config mcux_mcan_config_##n = { \
|
||||||
|
.base = (mm_reg_t)DT_INST_REG_ADDR(n), \
|
||||||
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
|
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
|
||||||
.clock_subsys = (clock_control_subsys_t) \
|
.clock_subsys = (clock_control_subsys_t) \
|
||||||
DT_INST_CLOCKS_CELL(n, name), \
|
DT_INST_CLOCKS_CELL(n, name), \
|
||||||
|
@ -150,7 +168,9 @@ static const struct can_driver_api mcux_mcan_driver_api = {
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
static const struct can_mcan_config can_mcan_config_##n = \
|
static const struct can_mcan_config can_mcan_config_##n = \
|
||||||
CAN_MCAN_DT_CONFIG_INST_GET(n, &mcux_mcan_config_##n); \
|
CAN_MCAN_DT_CONFIG_INST_GET(n, &mcux_mcan_config_##n, \
|
||||||
|
mcux_mcan_read_reg, \
|
||||||
|
mcux_mcan_write_reg); \
|
||||||
\
|
\
|
||||||
static struct mcux_mcan_data mcux_mcan_data_##n; \
|
static struct mcux_mcan_data mcux_mcan_data_##n; \
|
||||||
\
|
\
|
||||||
|
|
|
@ -20,6 +20,7 @@ LOG_MODULE_REGISTER(can_sam, CONFIG_CAN_LOG_LEVEL);
|
||||||
#define DT_DRV_COMPAT atmel_sam_can
|
#define DT_DRV_COMPAT atmel_sam_can
|
||||||
|
|
||||||
struct can_sam_config {
|
struct can_sam_config {
|
||||||
|
mm_reg_t base;
|
||||||
void (*config_irq)(void);
|
void (*config_irq)(void);
|
||||||
const struct atmel_sam_pmc_config clock_cfg;
|
const struct atmel_sam_pmc_config clock_cfg;
|
||||||
const struct pinctrl_dev_config *pcfg;
|
const struct pinctrl_dev_config *pcfg;
|
||||||
|
@ -30,6 +31,22 @@ struct can_sam_data {
|
||||||
struct can_mcan_msg_sram msg_ram;
|
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;
|
||||||
|
const struct can_sam_config *sam_config = mcan_config->custom;
|
||||||
|
|
||||||
|
return can_mcan_sys_read_reg(sam_config->base, reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int can_sam_write_reg(const struct device *dev, uint16_t reg, uint32_t val)
|
||||||
|
{
|
||||||
|
const struct can_mcan_config *mcan_config = dev->config;
|
||||||
|
const struct can_sam_config *sam_config = mcan_config->custom;
|
||||||
|
|
||||||
|
return can_mcan_sys_write_reg(sam_config->base, reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
static int can_sam_get_core_clock(const struct device *dev, uint32_t *rate)
|
static int can_sam_get_core_clock(const struct device *dev, uint32_t *rate)
|
||||||
{
|
{
|
||||||
const struct can_mcan_config *mcan_cfg = dev->config;
|
const struct can_mcan_config *mcan_cfg = dev->config;
|
||||||
|
@ -139,6 +156,7 @@ static void config_can_##inst##_irq(void)
|
||||||
|
|
||||||
#define CAN_SAM_CFG_INST(inst) \
|
#define CAN_SAM_CFG_INST(inst) \
|
||||||
static const struct can_sam_config can_sam_cfg_##inst = { \
|
static const struct can_sam_config can_sam_cfg_##inst = { \
|
||||||
|
.base = (mm_reg_t)DT_INST_REG_ADDR(inst), \
|
||||||
.clock_cfg = SAM_DT_INST_CLOCK_PMC_CFG(inst), \
|
.clock_cfg = SAM_DT_INST_CLOCK_PMC_CFG(inst), \
|
||||||
.divider = DT_INST_PROP(inst, divider), \
|
.divider = DT_INST_PROP(inst, divider), \
|
||||||
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
|
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
|
||||||
|
@ -146,7 +164,9 @@ static void config_can_##inst##_irq(void)
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
static const struct can_mcan_config can_mcan_cfg_##inst = \
|
static const struct can_mcan_config can_mcan_cfg_##inst = \
|
||||||
CAN_MCAN_DT_CONFIG_INST_GET(inst, &can_sam_cfg_##inst);
|
CAN_MCAN_DT_CONFIG_INST_GET(inst, &can_sam_cfg_##inst, \
|
||||||
|
can_sam_read_reg, \
|
||||||
|
can_sam_write_reg);
|
||||||
|
|
||||||
#define CAN_SAM_DATA_INST(inst) \
|
#define CAN_SAM_DATA_INST(inst) \
|
||||||
static struct can_sam_data can_sam_data_##inst; \
|
static struct can_sam_data can_sam_data_##inst; \
|
||||||
|
|
|
@ -30,6 +30,7 @@ LOG_MODULE_REGISTER(can_stm32fd, CONFIG_CAN_LOG_LEVEL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct can_stm32fd_config {
|
struct can_stm32fd_config {
|
||||||
|
mm_reg_t base;
|
||||||
size_t pclk_len;
|
size_t pclk_len;
|
||||||
const struct stm32_pclken *pclken;
|
const struct stm32_pclken *pclken;
|
||||||
void (*config_irq)(void);
|
void (*config_irq)(void);
|
||||||
|
@ -37,6 +38,22 @@ struct can_stm32fd_config {
|
||||||
uint8_t clock_divider;
|
uint8_t clock_divider;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int can_stm32fd_read_reg(const struct device *dev, uint16_t reg, uint32_t *val)
|
||||||
|
{
|
||||||
|
const struct can_mcan_config *mcan_config = dev->config;
|
||||||
|
const struct can_stm32fd_config *stm32fd_config = mcan_config->custom;
|
||||||
|
|
||||||
|
return can_mcan_sys_read_reg(stm32fd_config->base, reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int can_stm32fd_write_reg(const struct device *dev, uint16_t reg, uint32_t val)
|
||||||
|
{
|
||||||
|
const struct can_mcan_config *mcan_config = dev->config;
|
||||||
|
const struct can_stm32fd_config *stm32fd_config = mcan_config->custom;
|
||||||
|
|
||||||
|
return can_mcan_sys_write_reg(stm32fd_config->base, reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
static int can_stm32fd_get_core_clock(const struct device *dev, uint32_t *rate)
|
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);
|
const uint32_t rate_tmp = LL_RCC_GetFDCANClockFreq(LL_RCC_FDCAN_CLKSOURCE);
|
||||||
|
@ -190,6 +207,7 @@ static void config_can_##inst##_irq(void) \
|
||||||
STM32_DT_INST_CLOCKS(inst); \
|
STM32_DT_INST_CLOCKS(inst); \
|
||||||
\
|
\
|
||||||
static const struct can_stm32fd_config can_stm32fd_cfg_##inst = { \
|
static const struct can_stm32fd_config can_stm32fd_cfg_##inst = { \
|
||||||
|
.base = (mm_reg_t)DT_INST_REG_ADDR_BY_NAME(inst, m_can), \
|
||||||
.pclken = can_stm32fd_pclken_##inst, \
|
.pclken = can_stm32fd_pclken_##inst, \
|
||||||
.pclk_len = DT_INST_NUM_CLOCKS(inst), \
|
.pclk_len = DT_INST_NUM_CLOCKS(inst), \
|
||||||
.config_irq = config_can_##inst##_irq, \
|
.config_irq = config_can_##inst##_irq, \
|
||||||
|
@ -198,7 +216,9 @@ static void config_can_##inst##_irq(void) \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
static const struct can_mcan_config can_mcan_cfg_##inst = \
|
static const struct can_mcan_config can_mcan_cfg_##inst = \
|
||||||
CAN_MCAN_DT_CONFIG_INST_GET(inst, &can_stm32fd_cfg_##inst);
|
CAN_MCAN_DT_CONFIG_INST_GET(inst, &can_stm32fd_cfg_##inst, \
|
||||||
|
can_stm32fd_read_reg, \
|
||||||
|
can_stm32fd_write_reg);
|
||||||
|
|
||||||
#define CAN_STM32FD_DATA_INST(inst) \
|
#define CAN_STM32FD_DATA_INST(inst) \
|
||||||
static struct can_mcan_data can_mcan_data_##inst = \
|
static struct can_mcan_data can_mcan_data_##inst = \
|
||||||
|
|
|
@ -21,11 +21,28 @@ LOG_MODULE_REGISTER(can_stm32h7, CONFIG_CAN_LOG_LEVEL);
|
||||||
#define DT_DRV_COMPAT st_stm32h7_fdcan
|
#define DT_DRV_COMPAT st_stm32h7_fdcan
|
||||||
|
|
||||||
struct can_stm32h7_config {
|
struct can_stm32h7_config {
|
||||||
|
mm_reg_t base;
|
||||||
void (*config_irq)(void);
|
void (*config_irq)(void);
|
||||||
const struct pinctrl_dev_config *pcfg;
|
const struct pinctrl_dev_config *pcfg;
|
||||||
struct stm32_pclken pclken;
|
struct stm32_pclken pclken;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
return can_mcan_sys_read_reg(stm32h7_config->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;
|
||||||
|
|
||||||
|
return can_mcan_sys_write_reg(stm32h7_config->base, reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
static int can_stm32h7_get_core_clock(const struct device *dev, uint32_t *rate)
|
static int can_stm32h7_get_core_clock(const struct device *dev, uint32_t *rate)
|
||||||
{
|
{
|
||||||
const uint32_t rate_tmp = LL_RCC_GetFDCANClockFreq(LL_RCC_FDCAN_CLKSOURCE);
|
const uint32_t rate_tmp = LL_RCC_GetFDCANClockFreq(LL_RCC_FDCAN_CLKSOURCE);
|
||||||
|
@ -164,6 +181,7 @@ static const struct can_driver_api can_stm32h7_driver_api = {
|
||||||
PINCTRL_DT_INST_DEFINE(n); \
|
PINCTRL_DT_INST_DEFINE(n); \
|
||||||
\
|
\
|
||||||
static const struct can_stm32h7_config can_stm32h7_cfg_##n = { \
|
static const struct can_stm32h7_config can_stm32h7_cfg_##n = { \
|
||||||
|
.base = (mm_reg_t)DT_INST_REG_ADDR_BY_NAME(n, m_can), \
|
||||||
.config_irq = stm32h7_mcan_irq_config_##n, \
|
.config_irq = stm32h7_mcan_irq_config_##n, \
|
||||||
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
|
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
|
||||||
.pclken = { \
|
.pclken = { \
|
||||||
|
@ -173,7 +191,9 @@ static const struct can_driver_api can_stm32h7_driver_api = {
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
static const struct can_mcan_config can_mcan_cfg_##n = \
|
static const struct can_mcan_config can_mcan_cfg_##n = \
|
||||||
CAN_MCAN_DT_CONFIG_INST_GET(n, &can_stm32h7_cfg_##n); \
|
CAN_MCAN_DT_CONFIG_INST_GET(n, &can_stm32h7_cfg_##n, \
|
||||||
|
can_stm32h7_read_reg, \
|
||||||
|
can_stm32h7_write_reg); \
|
||||||
\
|
\
|
||||||
static struct can_mcan_data can_mcan_data_##n = \
|
static struct can_mcan_data can_mcan_data_##n = \
|
||||||
CAN_MCAN_DATA_INITIALIZER((struct can_mcan_msg_sram *) \
|
CAN_MCAN_DATA_INITIALIZER((struct can_mcan_msg_sram *) \
|
||||||
|
|
|
@ -422,7 +422,6 @@
|
||||||
can0: can@40030000 {
|
can0: can@40030000 {
|
||||||
compatible = "atmel,sam-can";
|
compatible = "atmel,sam-can";
|
||||||
reg = <0x40030000 0x100>;
|
reg = <0x40030000 0x100>;
|
||||||
reg-names = "m_can";
|
|
||||||
interrupts = <35 0>, <36 0>;
|
interrupts = <35 0>, <36 0>;
|
||||||
interrupt-names = "LINE_0", "LINE_1";
|
interrupt-names = "LINE_0", "LINE_1";
|
||||||
clocks = <&pmc PMC_TYPE_PERIPHERAL 35>;
|
clocks = <&pmc PMC_TYPE_PERIPHERAL 35>;
|
||||||
|
@ -437,7 +436,6 @@
|
||||||
can1: can@40034000 {
|
can1: can@40034000 {
|
||||||
compatible = "atmel,sam-can";
|
compatible = "atmel,sam-can";
|
||||||
reg = <0x40034000 0x100>;
|
reg = <0x40034000 0x100>;
|
||||||
reg-names = "m_can";
|
|
||||||
interrupts = <37 0>, <38 0>;
|
interrupts = <37 0>, <38 0>;
|
||||||
interrupt-names = "LINE_0", "LINE_1";
|
interrupt-names = "LINE_0", "LINE_1";
|
||||||
clocks = <&pmc PMC_TYPE_PERIPHERAL 37>;
|
clocks = <&pmc PMC_TYPE_PERIPHERAL 37>;
|
||||||
|
|
|
@ -220,7 +220,6 @@
|
||||||
can0: can@9d000 {
|
can0: can@9d000 {
|
||||||
compatible = "nxp,lpc-mcan";
|
compatible = "nxp,lpc-mcan";
|
||||||
reg = <0x9d000 0x1000>;
|
reg = <0x9d000 0x1000>;
|
||||||
reg-names = "m_can";
|
|
||||||
interrupts = <43 0>, <44 0>;
|
interrupts = <43 0>, <44 0>;
|
||||||
clocks = <&syscon MCUX_MCAN_CLK>;
|
clocks = <&syscon MCUX_MCAN_CLK>;
|
||||||
std-filter-elements = <15>;
|
std-filter-elements = <15>;
|
||||||
|
|
|
@ -214,7 +214,6 @@
|
||||||
can0: can@9d000 {
|
can0: can@9d000 {
|
||||||
compatible = "nxp,lpc-mcan";
|
compatible = "nxp,lpc-mcan";
|
||||||
reg = <0x9d000 0x1000>;
|
reg = <0x9d000 0x1000>;
|
||||||
reg-names = "m_can";
|
|
||||||
interrupts = <43 0>, <44 0>;
|
interrupts = <43 0>, <44 0>;
|
||||||
clocks = <&syscon MCUX_MCAN_CLK>;
|
clocks = <&syscon MCUX_MCAN_CLK>;
|
||||||
std-filter-elements = <15>;
|
std-filter-elements = <15>;
|
||||||
|
|
|
@ -257,7 +257,6 @@
|
||||||
can0: can@4009d000 {
|
can0: can@4009d000 {
|
||||||
compatible = "nxp,lpc-mcan";
|
compatible = "nxp,lpc-mcan";
|
||||||
reg = <0x4009d000 0x1000>;
|
reg = <0x4009d000 0x1000>;
|
||||||
reg-names = "m_can";
|
|
||||||
interrupts = <43 0>, <44 0>;
|
interrupts = <43 0>, <44 0>;
|
||||||
clocks = <&syscon MCUX_MCAN_CLK>;
|
clocks = <&syscon MCUX_MCAN_CLK>;
|
||||||
std-filter-elements = <15>;
|
std-filter-elements = <15>;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue