diff --git a/drivers/can/can_nrf.c b/drivers/can/can_nrf.c index b4e6dbd49be..0b32c50abfe 100644 --- a/drivers/can/can_nrf.c +++ b/drivers/can/can_nrf.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -27,7 +28,8 @@ struct can_nrf_config { uint32_t mcan; uint32_t mrba; uint32_t mram; - const struct device *clock; + const struct device *auxpll; + const struct device *hsfll; const struct pinctrl_dev_config *pcfg; void (*irq_configure)(void); uint16_t irq; @@ -54,7 +56,7 @@ static int can_nrf_get_core_clock(const struct device *dev, uint32_t *rate) const struct can_mcan_config *mcan_config = dev->config; const struct can_nrf_config *config = mcan_config->custom; - return clock_control_get_rate(config->clock, NULL, rate); + return clock_control_get_rate(config->auxpll, NULL, rate); } static DEVICE_API(can, can_nrf_api) = { @@ -131,17 +133,41 @@ static const struct can_mcan_ops can_mcan_nrf_ops = { .clear_mram = can_nrf_clear_mram, }; +static int configure_hsfll(const struct device *dev, bool on) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct can_nrf_config *config = mcan_config->custom; + struct nrf_clock_spec spec = { 0 }; + + /* If CAN is on, HSFLL frequency >= AUXPLL frequency */ + if (on) { + int ret; + + ret = clock_control_get_rate(dev, NULL, &spec.frequency); + if (ret < 0) { + return ret; + } + } + + return nrf_clock_control_request_sync(config->hsfll, &spec, K_FOREVER); +} + static int can_nrf_init(const struct device *dev) { const struct can_mcan_config *mcan_config = dev->config; const struct can_nrf_config *config = mcan_config->custom; int ret; - if (!device_is_ready(config->clock)) { + if (!device_is_ready(config->auxpll) || !device_is_ready(config->hsfll)) { return -ENODEV; } - ret = clock_control_on(config->clock, NULL); + ret = configure_hsfll(dev, true); + if (ret < 0) { + return ret; + } + + ret = clock_control_on(config->auxpll, NULL); if (ret < 0) { return ret; } @@ -186,8 +212,9 @@ static int can_nrf_init(const struct device *dev) .mcan = CAN_MCAN_DT_INST_MCAN_ADDR(n), \ .mrba = CAN_MCAN_DT_INST_MRBA(n), \ .mram = CAN_MCAN_DT_INST_MRAM_ADDR(n), \ - .clock = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .auxpll = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_NAME(n, auxpll)), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .hsfll = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_NAME(n, hsfll)), \ .irq = DT_INST_IRQN(n), \ .irq_configure = can_nrf_irq_configure##n, \ }; \