Skip to content

Commit 4a4a94b

Browse files
gmarullcfriedt
authored andcommitted
drivers: clock_control: sf32lb_rcc: add support for DLL2
Add support for configuring and enabling DLL2. A few things have been simplified (common PMUC, just store frequency, etc.). Signed-off-by: Gerard Marull-Paretas <[email protected]>
1 parent ebb316d commit 4a4a94b

File tree

1 file changed

+74
-41
lines changed

1 file changed

+74
-41
lines changed

drivers/clock_control/clock_control_sf32lb_rcc.c

Lines changed: 74 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -23,29 +23,54 @@
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

3941
struct 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+
4974
static 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 */
162186
IF_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

171204
static 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

185218
DEVICE_DT_INST_DEFINE(0, clock_control_sf32lb_rcc_init, NULL, NULL, &config, PRE_KERNEL_1,

0 commit comments

Comments
 (0)