2323#define HPSYS_RCC_CSR offsetof(HPSYS_RCC_TypeDef, CSR)
2424#define HPSYS_RCC_CFGR offsetof(HPSYS_RCC_TypeDef, CFGR)
2525#define HPSYS_RCC_DLL1CR offsetof(HPSYS_RCC_TypeDef, DLL1CR)
26+ #define HPSYS_RCC_DLL2CR offsetof(HPSYS_RCC_TypeDef, DLL2CR)
2627
2728#define HPSYS_RCC_CSR_SEL_SYS_CLK_HXT48 FIELD_PREP(HPSYS_RCC_CSR_SEL_SYS_Msk, 1U)
2829#define HPSYS_RCC_CSR_SEL_SYS_CLK_DLL1 FIELD_PREP(HPSYS_RCC_CSR_SEL_SYS_Msk, 3U)
30+ #define HPSYS_RCC_CSR_SEL_MPI1_CLK_DLL2 FIELD_PREP(HPSYS_RCC_CSR_SEL_MPI1_Msk, 2U)
31+ #define HPSYS_RCC_CSR_SEL_MPI2_CLK_DLL2 FIELD_PREP(HPSYS_RCC_CSR_SEL_MPI2_Msk, 2U)
2932#define HPSYS_RCC_CSR_SEL_PERI_CLK_HXT48 FIELD_PREP(HPSYS_RCC_CSR_SEL_PERI_Msk, 1U)
3033
31- #define HPSYS_RCC_DLL1CR_STG_STEP 24000000UL
32-
33- struct clock_control_sf32lb_rcc_dll_config {
34- bool enabled ;
35- uintptr_t pmuc ;
36- uint32_t freq ;
37- };
34+ #define HPSYS_RCC_DLLXCR_EN HPSYS_RCC_DLL1CR_EN
35+ #define HPSYS_RCC_DLLXCR_STG_Msk HPSYS_RCC_DLL1CR_STG_Msk
36+ #define HPSYS_RCC_DLLXCR_STG_STEP 24000000UL
37+ #define HPSYS_RCC_DLLXCR_IN_DIV2_EN HPSYS_RCC_DLL1CR_IN_DIV2_EN
38+ #define HPSYS_RCC_DLLXCR_OUT_DIV2_EN HPSYS_RCC_DLL1CR_OUT_DIV2_EN
39+ #define HPSYS_RCC_DLLXCR_READY HPSYS_RCC_DLL1CR_READY
3840
3941struct clock_control_sf32lb_rcc_config {
4042 uintptr_t base ;
4143 uintptr_t cfg ;
44+ uintptr_t pmuc ;
4245 uint8_t hdiv ;
4346 uint8_t pdiv1 ;
4447 uint8_t pdiv2 ;
45- struct clock_control_sf32lb_rcc_dll_config dll1 ;
48+ uint32_t dll1_freq ;
49+ uint32_t dll2_freq ;
4650 const struct device * hxt48 ;
4751};
4852
53+ static inline void configure_dll (const struct device * dev , uint32_t freq , uint32_t dllxcr )
54+ {
55+ const struct clock_control_sf32lb_rcc_config * config = dev -> config ;
56+ uint32_t val ;
57+
58+ /* disable DLLX, clear modified fields */
59+ val = sys_read32 (config -> base + dllxcr );
60+ val &= ~HPSYS_RCC_DLLXCR_EN ;
61+ sys_write32 (val , config -> base + dllxcr );
62+
63+ /* configure DLLX */
64+ val &= ~(HPSYS_RCC_DLLXCR_STG_Msk | HPSYS_RCC_DLLXCR_OUT_DIV2_EN );
65+ val |= FIELD_PREP (HPSYS_RCC_DLLXCR_STG_Msk , (freq / HPSYS_RCC_DLLXCR_STG_STEP ) - 1U ) |
66+ HPSYS_RCC_DLLXCR_IN_DIV2_EN | HPSYS_RCC_DLLXCR_EN ;
67+ sys_write32 (val , config -> base + dllxcr );
68+
69+ do {
70+ val = sys_read32 (config -> base + dllxcr );
71+ } while ((val & HPSYS_RCC_DLLXCR_READY ) == 0U );
72+ }
73+
4974static int clock_control_sf32lb_rcc_on (const struct device * dev , clock_control_subsys_t sys )
5075{
5176 const struct clock_control_sf32lb_rcc_config * config = dev -> config ;
@@ -108,35 +133,33 @@ static int clock_control_sf32lb_rcc_init(const struct device *dev)
108133 sys_write32 (val , config -> base + HPSYS_RCC_CSR );
109134 }
110135
111- if (config -> dll1 . enabled ) {
112- val = sys_read32 (config -> dll1 . pmuc + PMUC_HXT_CR1 );
136+ if (config -> dll1_freq != 0U || config -> dll2_freq != 0U ) {
137+ val = sys_read32 (config -> pmuc + PMUC_HXT_CR1 );
113138 val |= PMUC_HXT_CR1_BUF_DLL_EN ;
114- sys_write32 (val , config -> dll1 . pmuc + PMUC_HXT_CR1 );
139+ sys_write32 (val , config -> pmuc + PMUC_HXT_CR1 );
115140
116141 val = sys_read32 (config -> cfg + HPSYS_CFG_CAU2_CR );
117142 val |= HPSYS_CFG_CAU2_CR_HPBG_EN | HPSYS_CFG_CAU2_CR_HPBG_VDDPSW_EN ;
118143 sys_write32 (val , config -> cfg + HPSYS_CFG_CAU2_CR );
119144
120- /* disable DLL1, clear modified fields */
121- val = sys_read32 (config -> base + HPSYS_RCC_DLL1CR );
122- val &= ~HPSYS_RCC_DLL1CR_EN ;
123- sys_write32 (val , config -> base + HPSYS_RCC_DLL1CR );
145+ val = sys_read32 (config -> base + HPSYS_RCC_CSR );
124146
125- /* configure DLL1 */
126- val &= ~(HPSYS_RCC_DLL1CR_STG_Msk | HPSYS_RCC_DLL1CR_OUT_DIV2_EN );
127- val |= FIELD_PREP (HPSYS_RCC_DLL1CR_STG_Msk ,
128- (config -> dll1 .freq / HPSYS_RCC_DLL1CR_STG_STEP ) - 1U ) |
129- HPSYS_RCC_DLL1CR_IN_DIV2_EN | HPSYS_RCC_DLL1CR_EN ;
130- sys_write32 (val , config -> base + HPSYS_RCC_DLL1CR );
147+ if (config -> dll1_freq != 0U ) {
148+ configure_dll (dev , config -> dll1_freq , HPSYS_RCC_DLL1CR );
131149
132- do {
133- val = sys_read32 (config -> base + HPSYS_RCC_DLL1CR );
134- } while ((val & HPSYS_RCC_DLL1CR_READY ) == 0U );
150+ /* TODO: make this configurable */
151+ val &= ~HPSYS_RCC_CSR_SEL_SYS_Msk ;
152+ val |= HPSYS_RCC_CSR_SEL_SYS_CLK_DLL1 ;
153+ }
154+
155+ if (config -> dll2_freq != 0U ) {
156+ configure_dll (dev , config -> dll2_freq , HPSYS_RCC_DLL2CR );
157+
158+ /* TODO: make this configurable */
159+ val &= ~(HPSYS_RCC_CSR_SEL_MPI1_Msk | HPSYS_RCC_CSR_SEL_MPI2_Msk );
160+ val |= HPSYS_RCC_CSR_SEL_MPI1_CLK_DLL2 | HPSYS_RCC_CSR_SEL_MPI2_CLK_DLL2 ;
161+ }
135162
136- /* TODO: make this configurable */
137- val = sys_read32 (config -> base + HPSYS_RCC_CSR );
138- val &= ~HPSYS_RCC_CSR_SEL_SYS_Msk ;
139- val |= HPSYS_RCC_CSR_SEL_SYS_CLK_DLL1 ;
140163 sys_write32 (val , config -> base + HPSYS_RCC_CSR );
141164 }
142165
@@ -151,35 +174,45 @@ static int clock_control_sf32lb_rcc_init(const struct device *dev)
151174 return 0 ;
152175}
153176
154- /* DLL1 requires HXT48 */
155- IF_ENABLED (DT_NODE_HAS_STATUS (DT_INST_CHILD (0 , dll1 ), okay ), (
156- BUILD_ASSERT (
177+ /* DLL1/2 requires HXT48 */
178+ IF_ENABLED (UTIL_OR (
179+ DT_NODE_HAS_STATUS (DT_INST_CHILD (0 , dll1 ), okay ),
180+ DT_NODE_HAS_STATUS (DT_INST_CHILD (0 , dll2 ), okay )),
181+ (BUILD_ASSERT (
157182 (DT_NODE_HAS_STATUS (DT_INST_CLOCKS_CTLR_BY_NAME (0 , hxt48 ), okay )),
158- "DLL1 requires HXT48 to be enabled"
159- );))
183+ "DLL1/2 require HXT48 to be enabled" );))
160184
161- /* DLL1 frequency must be a multiple of step size */
185+ /* DLL1/2 frequency must be a multiple of step size */
162186IF_ENABLED (DT_NODE_HAS_STATUS (DT_INST_CHILD (0 , dll1 ), okay ), (
163187 BUILD_ASSERT (
164188 ((DT_PROP (DT_INST_CHILD (0 , dll1 ), clock_frequency ) != 0 ) &&
165189 ((DT_PROP (DT_INST_CHILD (0 , dll1 ), clock_frequency ) %
166- HPSYS_RCC_DLL1CR_STG_STEP ) == 0 )),
190+ HPSYS_RCC_DLLXCR_STG_STEP ) == 0 )),
167191 "DLL1 frequency must be a non-zero multiple of "
168- STRINGIFY (HPSYS_RCC_DLL1CR_STG_STEP )
192+ STRINGIFY (HPSYS_RCC_DLLXCR_STG_STEP )
193+ );))
194+
195+ IF_ENABLED (DT_NODE_HAS_STATUS (DT_INST_CHILD (0 , dll2 ), okay ), (
196+ BUILD_ASSERT (
197+ ((DT_PROP (DT_INST_CHILD (0 , dll2 ), clock_frequency ) != 0 ) &&
198+ ((DT_PROP (DT_INST_CHILD (0 , dll2 ), clock_frequency ) %
199+ HPSYS_RCC_DLLXCR_STG_STEP ) == 0 )),
200+ "DLL2 frequency must be a non-zero multiple of "
201+ STRINGIFY (HPSYS_RCC_DLLXCR_STG_STEP )
169202 );))
170203
171204static const struct clock_control_sf32lb_rcc_config config = {
172205 .base = DT_REG_ADDR (DT_INST_PARENT (0 )),
173206 .cfg = DT_REG_ADDR (DT_INST_PHANDLE (0 , sifli_cfg )),
207+ .pmuc = DT_REG_ADDR (DT_INST_PHANDLE (0 , sifli_pmuc )),
174208 .hxt48 = DEVICE_DT_GET_OR_NULL (DT_INST_CLOCKS_CTLR_BY_NAME (0 , hxt48 )),
175209 .hdiv = DT_INST_PROP (0 , sifli_hdiv ),
176210 .pdiv1 = DT_INST_PROP (0 , sifli_pdiv1 ),
177211 .pdiv2 = DT_INST_PROP (0 , sifli_pdiv2 ),
178- .dll1 = {
179- .enabled = DT_NODE_HAS_STATUS (DT_INST_CHILD (0 , dll1 ), okay ),
180- .pmuc = DT_REG_ADDR (DT_INST_PHANDLE (0 , sifli_pmuc )),
181- .freq = DT_PROP (DT_INST_CHILD (0 , dll1 ), clock_frequency ),
182- },
212+ .dll1_freq = COND_CODE_1 (DT_NODE_HAS_STATUS (DT_INST_CHILD (0 , dll1 ), okay ),
213+ (DT_PROP (DT_INST_CHILD (0 , dll1 ), clock_frequency )), (0U )),
214+ .dll2_freq = COND_CODE_1 (DT_NODE_HAS_STATUS (DT_INST_CHILD (0 , dll2 ), okay ),
215+ (DT_PROP (DT_INST_CHILD (0 , dll2 ), clock_frequency )), (0U )),
183216};
184217
185218DEVICE_DT_INST_DEFINE (0 , clock_control_sf32lb_rcc_init , NULL , NULL , & config , PRE_KERNEL_1 ,
0 commit comments