drivers: can: flexcan: disable self-reception and support listen-only
Add work-around for the NXP MCUxpresso SDK not exposing APIs for setting the listen-only (LOM) bit of the FlexCAN MCR register and the self-reception disable (SRXDIS) bit of the CTRL1 register. These bits can only be written when the FlexCAN module is in freeze mode. Add a set of simplified functions (not supporting errata 9595) for entering/exiting freeze mode. This work-around can be removed again once the NXP MCUxpresso SDK exposes the needed functionality. Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
parent
2ac5841928
commit
8940c25145
1 changed files with 47 additions and 1 deletions
|
@ -88,6 +88,39 @@ struct mcux_flexcan_data {
|
||||||
struct mcux_flexcan_tx_callback tx_cbs[MCUX_FLEXCAN_MAX_TX];
|
struct mcux_flexcan_tx_callback tx_cbs[MCUX_FLEXCAN_MAX_TX];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if (!defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_9595) || \
|
||||||
|
!FSL_FEATURE_FLEXCAN_HAS_ERRATA_9595)
|
||||||
|
static void mcux_flexcan_freeze(struct device *dev)
|
||||||
|
{
|
||||||
|
const struct mcux_flexcan_config *config = dev->config->config_info;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simple freeze implementation without support for
|
||||||
|
* FSL_FEATURE_FLEXCAN_HAS_ERRATA_9595.
|
||||||
|
*
|
||||||
|
* This can be removed once the MCUX FlexCAN driver supports
|
||||||
|
* setting the MCR->LOM and CTRL1->SRXDIS bits or exposes its
|
||||||
|
* internal freeze/unfreeze functions through the API.
|
||||||
|
*/
|
||||||
|
config->base->MCR |= CAN_MCR_FRZ_MASK;
|
||||||
|
config->base->MCR |= CAN_MCR_HALT_MASK;
|
||||||
|
|
||||||
|
while ((config->base->MCR & CAN_MCR_FRZACK_MASK) == 0U) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mcux_flexcan_thaw(struct device *dev)
|
||||||
|
{
|
||||||
|
const struct mcux_flexcan_config *config = dev->config->config_info;
|
||||||
|
|
||||||
|
config->base->MCR &= ~CAN_MCR_HALT_MASK;
|
||||||
|
config->base->MCR &= ~CAN_MCR_FRZ_MASK;
|
||||||
|
|
||||||
|
while ((config->base->MCR & CAN_MCR_FRZACK_MASK) != 0U) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int mcux_flexcan_configure(struct device *dev, enum can_mode mode,
|
static int mcux_flexcan_configure(struct device *dev, enum can_mode mode,
|
||||||
u32_t bitrate)
|
u32_t bitrate)
|
||||||
{
|
{
|
||||||
|
@ -96,10 +129,12 @@ static int mcux_flexcan_configure(struct device *dev, enum can_mode mode,
|
||||||
struct device *clock_dev;
|
struct device *clock_dev;
|
||||||
u32_t clock_freq;
|
u32_t clock_freq;
|
||||||
|
|
||||||
/* TODO: support silent mode */
|
#if (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_9595) && \
|
||||||
|
FSL_FEATURE_FLEXCAN_HAS_ERRATA_9595)
|
||||||
if (mode == CAN_SILENT_MODE || mode == CAN_SILENT_LOOPBACK_MODE) {
|
if (mode == CAN_SILENT_MODE || mode == CAN_SILENT_LOOPBACK_MODE) {
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
clock_dev = device_get_binding(config->clock_name);
|
clock_dev = device_get_binding(config->clock_name);
|
||||||
if (clock_dev == NULL) {
|
if (clock_dev == NULL) {
|
||||||
|
@ -124,6 +159,17 @@ static int mcux_flexcan_configure(struct device *dev, enum can_mode mode,
|
||||||
|
|
||||||
FLEXCAN_Init(config->base, &flexcan_config, clock_freq);
|
FLEXCAN_Init(config->base, &flexcan_config, clock_freq);
|
||||||
|
|
||||||
|
#if (!defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_9595) || \
|
||||||
|
!FSL_FEATURE_FLEXCAN_HAS_ERRATA_9595)
|
||||||
|
mcux_flexcan_freeze(dev);
|
||||||
|
if (mode == CAN_SILENT_MODE || mode == CAN_SILENT_LOOPBACK_MODE) {
|
||||||
|
config->base->CTRL1 |= CAN_CTRL1_LOM(1);
|
||||||
|
}
|
||||||
|
/* Disable self reception */
|
||||||
|
config->base->MCR |= CAN_MCR_SRXDIS(1);
|
||||||
|
mcux_flexcan_thaw(dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue