diff --git a/drivers/can/Kconfig.sam b/drivers/can/Kconfig.sam index 919a73328d9c4..8952f4d1ae758 100644 --- a/drivers/can/Kconfig.sam +++ b/drivers/can/Kconfig.sam @@ -8,15 +8,3 @@ config CAN_SAM bool "Atmel SAM CAN driver" default $(dt_compat_enabled,$(DT_COMPAT_ATMEL_SAM_CAN)) select CAN_MCAN - -if CAN_SAM - -config CAN_SAM_CKDIV - int "Clock divider" - range 0 255 - default 0 - depends on CAN_SAM - help - Clock divider for the MCAN core clock. - -endif #CAN_SAM diff --git a/drivers/can/can_sam.c b/drivers/can/can_sam.c index 6309d4bd92cb4..56aef49565d98 100644 --- a/drivers/can/can_sam.c +++ b/drivers/can/can_sam.c @@ -21,6 +21,7 @@ struct can_sam_config { void (*config_irq)(void); const struct pinctrl_dev_config *pcfg; uint8_t pmc_id; + int divider; }; struct can_sam_data { @@ -29,18 +30,20 @@ struct can_sam_data { static int can_sam_get_core_clock(const struct device *dev, uint32_t *rate) { - ARG_UNUSED(dev); + const struct can_mcan_config *mcan_cfg = dev->config; + const struct can_sam_config *sam_cfg = mcan_cfg->custom; - *rate = SOC_ATMEL_SAM_MCK_FREQ_HZ / (CONFIG_CAN_SAM_CKDIV + 1); + *rate = SOC_ATMEL_SAM_UPLLCK_FREQ_HZ / (sam_cfg->divider); return 0; } -static void can_sam_clock_enable(const struct can_sam_config *cfg) +static void can_sam_clock_enable(const struct can_sam_config *sam_cfg) { - REG_PMC_PCK5 = PMC_PCK_CSS_PLLA_CLK | PMC_PCK_PRES(CONFIG_CAN_SAM_CKDIV); + REG_PMC_PCK5 = PMC_PCK_CSS_UPLL_CLK | PMC_PCK_PRES(sam_cfg->divider - 1); PMC->PMC_SCER |= PMC_SCER_PCK5; - soc_pmc_peripheral_enable(cfg->pmc_id); + + soc_pmc_peripheral_enable(sam_cfg->pmc_id); } static int can_sam_init(const struct device *dev) @@ -129,6 +132,7 @@ static void config_can_##inst##_irq(void) #define CAN_SAM_CFG_INST(inst) \ static const struct can_sam_config can_sam_cfg_##inst = { \ .pmc_id = DT_INST_PROP(inst, peripheral_id), \ + .divider = DT_INST_PROP(inst, divider), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ .config_irq = config_can_##inst##_irq, \ }; \ diff --git a/dts/arm/atmel/same70.dtsi b/dts/arm/atmel/same70.dtsi index df4e85e271ea6..94036b7e862ea 100644 --- a/dts/arm/atmel/same70.dtsi +++ b/dts/arm/atmel/same70.dtsi @@ -438,13 +438,12 @@ can0: can@40030000 { compatible = "atmel,sam-can"; - #address-cells = <1>; - #size-cells = <0>; reg = <0x40030000 0x100>; reg-names = "m_can"; interrupts = <35 0>, <36 0>; interrupt-names = "LINE_0", "LINE_1"; peripheral-id = <35>; + divider = <6>; sjw = <1>; sample-point = <875>; sjw-data = <1>; @@ -455,13 +454,12 @@ can1: can@40034000 { compatible = "atmel,sam-can"; - #address-cells = <1>; - #size-cells = <0>; reg = <0x40034000 0x100>; reg-names = "m_can"; interrupts = <37 0>, <38 0>; interrupt-names = "LINE_0", "LINE_1"; peripheral-id = <37>; + divider = <6>; sjw = <1>; sample-point = <875>; sjw-data = <1>; diff --git a/dts/bindings/can/atmel,sam-can.yaml b/dts/bindings/can/atmel,sam-can.yaml index e441a2d870351..837c8615837ac 100644 --- a/dts/bindings/can/atmel,sam-can.yaml +++ b/dts/bindings/can/atmel,sam-can.yaml @@ -17,3 +17,12 @@ properties: type: int required: true description: peripheral ID + + divider: + type: int + required: true + enum: + - 6 + - 12 + - 24 + description: Clock divider for the CAN core clock diff --git a/soc/arm/atmel_sam/same70/soc.c b/soc/arm/atmel_sam/same70/soc.c index 2cefd1162bf4d..9ad8c498f73de 100644 --- a/soc/arm/atmel_sam/same70/soc.c +++ b/soc/arm/atmel_sam/same70/soc.c @@ -177,6 +177,14 @@ static ALWAYS_INLINE void clock_init(void) ; } + /* Setup UPLL */ + PMC->CKGR_UCKR = CKGR_UCKR_UPLLCOUNT(0x3Fu) | CKGR_UCKR_UPLLEN; + + /* Wait for PLL lock */ + while (!(PMC->PMC_SR & PMC_SR_LOCKU)) { + ; + } + /* * Final setup of the Master Clock */ diff --git a/soc/arm/atmel_sam/same70/soc.h b/soc/arm/atmel_sam/same70/soc.h index 1f9ba4d28920e..37f10e2792a0a 100644 --- a/soc/arm/atmel_sam/same70/soc.h +++ b/soc/arm/atmel_sam/same70/soc.h @@ -73,6 +73,9 @@ #define SOC_ATMEL_SAM_MCK_FREQ_HZ \ (SOC_ATMEL_SAM_HCLK_FREQ_HZ / CONFIG_SOC_ATMEL_SAME70_MDIV) +/** UTMI PLL clock (UPLLCK) Frequency */ +#define SOC_ATMEL_SAM_UPLLCK_FREQ_HZ MHZ(480) + #endif /* _ASMLANGUAGE */ #endif /* _ATMEL_SAME70_SOC_H_ */ diff --git a/soc/arm/atmel_sam/samv71/soc.c b/soc/arm/atmel_sam/samv71/soc.c index 2cbad87640694..232299c1b8f50 100644 --- a/soc/arm/atmel_sam/samv71/soc.c +++ b/soc/arm/atmel_sam/samv71/soc.c @@ -178,6 +178,14 @@ static ALWAYS_INLINE void clock_init(void) ; } + /* Setup UPLL */ + PMC->CKGR_UCKR = CKGR_UCKR_UPLLCOUNT(0x3Fu) | CKGR_UCKR_UPLLEN; + + /* Wait for PLL lock */ + while (!(PMC->PMC_SR & PMC_SR_LOCKU)) { + ; + } + /* * Final setup of the Master Clock */ diff --git a/soc/arm/atmel_sam/samv71/soc.h b/soc/arm/atmel_sam/samv71/soc.h index 0e5a3548d608e..264f92c5172e6 100644 --- a/soc/arm/atmel_sam/samv71/soc.h +++ b/soc/arm/atmel_sam/samv71/soc.h @@ -74,6 +74,9 @@ #define SOC_ATMEL_SAM_MCK_FREQ_HZ \ (SOC_ATMEL_SAM_HCLK_FREQ_HZ / CONFIG_SOC_ATMEL_SAMV71_MDIV) +/** UTMI PLL clock (UPLLCK) Frequency */ +#define SOC_ATMEL_SAM_UPLLCK_FREQ_HZ MHZ(480) + #endif /* _ASMLANGUAGE */ #include "pwm_fixup.h"