Files
zephyr/drivers/clock_control/clock_control_sf32lb_rcc.c
Qingsong Gou 9bdafbf23b drivers: clock_control: sf32lb: fix GPTIM2 clock rate
Fix GPTIM2 clock rate

Signed-off-by: Qingsong Gou <gouqs@hotmail.com>
2025-12-09 11:12:30 +01:00

492 lines
18 KiB
C

/*
* Copyright (c) 2025 Core Devices LLC
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT sifli_sf32lb_rcc_clk
#include <stdbool.h>
#include <stdint.h>
#include <zephyr/arch/cpu.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/clock_control/sf32lb.h>
#include <zephyr/dt-bindings/clock/sf32lb-clocks-common.h>
#include <zephyr/dt-bindings/clock/sf32lb52x-clocks.h>
#include <zephyr/sys/util.h>
#include <zephyr/toolchain.h>
#include <register.h>
#define HPSYS_CFG_CAU2_CR offsetof(HPSYS_CFG_TypeDef, CAU2_CR)
#define PMUC_HXT_CR1 offsetof(PMUC_TypeDef, HXT_CR1)
#define HPSYS_RCC_CSR offsetof(HPSYS_RCC_TypeDef, CSR)
#define HPSYS_RCC_CFGR offsetof(HPSYS_RCC_TypeDef, CFGR)
#define HPSYS_RCC_USBCR offsetof(HPSYS_RCC_TypeDef, USBCR)
#define HPSYS_RCC_DLL1CR offsetof(HPSYS_RCC_TypeDef, DLL1CR)
#define HPSYS_RCC_DLL2CR offsetof(HPSYS_RCC_TypeDef, DLL2CR)
#define HPSYS_RCC_DLLXCR_EN HPSYS_RCC_DLL1CR_EN
#define HPSYS_RCC_DLLXCR_STG_Msk HPSYS_RCC_DLL1CR_STG_Msk
#define HPSYS_RCC_DLLXCR_STG_STEP 24000000UL
#define HPSYS_RCC_DLLXCR_IN_DIV2_EN HPSYS_RCC_DLL1CR_IN_DIV2_EN
#define HPSYS_RCC_DLLXCR_OUT_DIV2_EN HPSYS_RCC_DLL1CR_OUT_DIV2_EN
#define HPSYS_RCC_DLLXCR_READY HPSYS_RCC_DLL1CR_READY
#define SF32LB_CLOCK_FREQ_BY_NAME(inst, name) \
DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(inst, name), clock_frequency)
#define SF32LB_DLL_FREQ(inst, node) \
COND_CODE_1(DT_NODE_HAS_STATUS(DT_INST_CHILD(inst, node), okay), \
(DT_PROP(DT_INST_CHILD(inst, node), clock_frequency)), (0U))
#define SF32LB_DLL1_FREQ(inst) SF32LB_DLL_FREQ(inst, dll1)
#define SF32LB_DLL2_FREQ(inst) SF32LB_DLL_FREQ(inst, dll2)
/* Enum values match the register field encoding used by RCC */
enum sf32lb_sys_clk_idx {
SF32LB_SYS_CLK_IDX_HRC48 = 0,
SF32LB_SYS_CLK_IDX_HXT48 = 1,
SF32LB_SYS_CLK_IDX_LPCLK = 2,
SF32LB_SYS_CLK_IDX_DLL1 = 3,
};
enum sf32lb_peri_clk_idx {
SF32LB_PERI_CLK_IDX_HRC48 = 0,
SF32LB_PERI_CLK_IDX_HXT48 = 1,
};
enum sf32lb_mpi_clk_idx {
SF32LB_MPI_CLK_IDX_PERI = 0,
SF32LB_MPI_CLK_IDX_DLL1 = 1,
SF32LB_MPI_CLK_IDX_DLL2 = 2,
};
enum sf32lb_usb_clk_idx {
SF32LB_USB_CLK_IDX_SYSCLK = 0,
SF32LB_USB_CLK_IDX_DLL2 = 1,
};
#define SF32LB_SYS_CLK_SRC_IDX(inst) \
DT_ENUM_IDX_OR(DT_DRV_INST(inst), sifli_sys_clk_src, SF32LB_SYS_CLK_IDX_HRC48)
#define SF32LB_PERI_CLK_SRC_IDX(inst) \
DT_ENUM_IDX_OR(DT_DRV_INST(inst), sifli_peri_clk_src, SF32LB_PERI_CLK_IDX_HXT48)
#define SF32LB_MPI1_CLK_SRC_IDX(inst) \
DT_ENUM_IDX_OR(DT_DRV_INST(inst), sifli_mpi1_clk_src, SF32LB_MPI_CLK_IDX_PERI)
#define SF32LB_MPI2_CLK_SRC_IDX(inst) \
DT_ENUM_IDX_OR(DT_DRV_INST(inst), sifli_mpi2_clk_src, SF32LB_MPI_CLK_IDX_PERI)
#define SF32LB_USB_CLK_SRC_IDX(inst) \
DT_ENUM_IDX_OR(DT_DRV_INST(inst), sifli_usb_clk_src, SF32LB_USB_CLK_IDX_SYSCLK)
#define SF32LB_SYS_CLK_SRC_VALUE(inst) SF32LB_SYS_CLK_SRC_IDX(inst)
#define SF32LB_PERI_CLK_SRC_VALUE(inst) SF32LB_PERI_CLK_SRC_IDX(inst)
#define SF32LB_MPI1_CLK_SRC_VALUE(inst) SF32LB_MPI1_CLK_SRC_IDX(inst)
#define SF32LB_MPI2_CLK_SRC_VALUE(inst) SF32LB_MPI2_CLK_SRC_IDX(inst)
#define SF32LB_USB_CLK_SRC_VALUE(inst) SF32LB_USB_CLK_SRC_IDX(inst)
#define SF32LB_SYS_CLK_FREQ(inst) \
((SF32LB_SYS_CLK_SRC_IDX(inst) == SF32LB_SYS_CLK_IDX_HRC48) \
? SF32LB_CLOCK_FREQ_BY_NAME(inst, hrc48) \
: (SF32LB_SYS_CLK_SRC_IDX(inst) == SF32LB_SYS_CLK_IDX_HXT48) \
? SF32LB_CLOCK_FREQ_BY_NAME(inst, hxt48) \
: (SF32LB_SYS_CLK_SRC_IDX(inst) == SF32LB_SYS_CLK_IDX_LPCLK) \
? SF32LB_CLOCK_FREQ_BY_NAME(inst, lrc32) \
: SF32LB_DLL1_FREQ(inst))
#define SF32LB_PERI_CLK_FREQ(inst) \
((SF32LB_PERI_CLK_SRC_IDX(inst) == SF32LB_PERI_CLK_IDX_HXT48) \
? SF32LB_CLOCK_FREQ_BY_NAME(inst, hxt48) \
: SF32LB_CLOCK_FREQ_BY_NAME(inst, hrc48))
#define SF32LB_USB_DIV_VALUE(inst) DT_INST_PROP_OR(DT_DRV_INST(inst), sifli_usb_div, 4)
#define SF32LB_RCC_NEEDS_HXT48(inst) \
(DT_NODE_HAS_STATUS(DT_INST_CHILD(inst, dll1), okay) || \
DT_NODE_HAS_STATUS(DT_INST_CHILD(inst, dll2), okay) || \
(SF32LB_SYS_CLK_SRC_IDX(inst) == SF32LB_SYS_CLK_IDX_HXT48) || \
(SF32LB_PERI_CLK_SRC_IDX(inst) == SF32LB_PERI_CLK_IDX_HXT48))
#define SF32LB_SYS_CLK_REQUIRES_DLL1(inst) (SF32LB_SYS_CLK_SRC_IDX(inst) == SF32LB_SYS_CLK_IDX_DLL1)
#define SF32LB_MPI1_CLK_REQUIRES_DLL2(inst) \
(SF32LB_MPI1_CLK_SRC_VALUE(inst) == SF32LB_MPI_CLK_IDX_DLL2)
#define SF32LB_MPI1_CLK_REQUIRES_DLL1(inst) \
(SF32LB_MPI1_CLK_SRC_VALUE(inst) == SF32LB_MPI_CLK_IDX_DLL1)
#define SF32LB_MPI2_CLK_REQUIRES_DLL2(inst) \
(SF32LB_MPI2_CLK_SRC_VALUE(inst) == SF32LB_MPI_CLK_IDX_DLL2)
#define SF32LB_MPI2_CLK_REQUIRES_DLL1(inst) \
(SF32LB_MPI2_CLK_SRC_VALUE(inst) == SF32LB_MPI_CLK_IDX_DLL1)
#define SF32LB_USB_CLK_REQUIRES_DLL2(inst) \
(SF32LB_USB_CLK_SRC_VALUE(inst) == SF32LB_USB_CLK_IDX_DLL2)
struct clock_control_sf32lb_rcc_config {
uintptr_t base;
uintptr_t cfg;
uintptr_t pmuc;
uint8_t hdiv;
uint8_t pdiv1;
uint8_t pdiv2;
uint8_t sys_clk_src;
uint8_t peri_clk_src;
uint8_t mpi1_clk_src;
uint8_t mpi2_clk_src;
uint8_t usb_clk_src;
uint8_t usb_div;
uint32_t sys_clk_freq;
uint32_t peri_clk_freq;
uint32_t hrc48_freq;
uint32_t hxt48_freq;
uint32_t lrc32_freq;
uint32_t lrc10_freq;
uint32_t lxt32_freq;
uint32_t dll1_freq;
uint32_t dll2_freq;
const struct device *hxt48;
};
static inline void configure_dll(const struct device *dev, uint32_t freq, uint32_t dllxcr)
{
const struct clock_control_sf32lb_rcc_config *config = dev->config;
uint32_t val;
/* disable DLLX, clear modified fields */
val = sys_read32(config->base + dllxcr);
val &= ~HPSYS_RCC_DLLXCR_EN;
sys_write32(val, config->base + dllxcr);
/* configure DLLX */
val &= ~(HPSYS_RCC_DLLXCR_STG_Msk | HPSYS_RCC_DLLXCR_OUT_DIV2_EN);
val |= FIELD_PREP(HPSYS_RCC_DLLXCR_STG_Msk, (freq / HPSYS_RCC_DLLXCR_STG_STEP) - 1U) |
HPSYS_RCC_DLLXCR_IN_DIV2_EN | HPSYS_RCC_DLLXCR_EN;
sys_write32(val, config->base + dllxcr);
do {
val = sys_read32(config->base + dllxcr);
} while ((val & HPSYS_RCC_DLLXCR_READY) == 0U);
}
static bool sf32lb_rcc_needs_hxt48(const struct clock_control_sf32lb_rcc_config *config)
{
return (config->sys_clk_src == SF32LB_SYS_CLK_IDX_HXT48) ||
(config->peri_clk_src == SF32LB_PERI_CLK_IDX_HXT48) || (config->dll1_freq != 0U) ||
(config->dll2_freq != 0U);
}
static uint32_t sf32lb_get_sys_clk(const struct clock_control_sf32lb_rcc_config *config)
{
return config->sys_clk_freq;
}
static uint32_t sf32lb_get_hclk(const struct clock_control_sf32lb_rcc_config *config)
{
uint32_t hdiv = config->hdiv;
if (hdiv == 0U) {
return sf32lb_get_sys_clk(config);
}
return sf32lb_get_sys_clk(config) / hdiv;
}
static uint32_t sf32lb_get_pclk1(const struct clock_control_sf32lb_rcc_config *config)
{
uint32_t divisor = BIT(config->pdiv1);
return sf32lb_get_hclk(config) / MAX(divisor, 1U);
}
static uint32_t sf32lb_get_clk_peri(const struct clock_control_sf32lb_rcc_config *config)
{
return config->peri_clk_freq;
}
static uint32_t sf32lb_get_mpi_clk(const struct clock_control_sf32lb_rcc_config *config,
uint8_t src)
{
switch (src) {
case SF32LB_MPI_CLK_IDX_DLL1:
return config->dll1_freq;
case SF32LB_MPI_CLK_IDX_DLL2:
return config->dll2_freq;
default:
return config->peri_clk_freq;
}
}
static uint32_t sf32lb_get_usb_clk(const struct clock_control_sf32lb_rcc_config *config)
{
uint32_t src = (config->usb_clk_src == SF32LB_USB_CLK_IDX_DLL2)
? config->dll2_freq
: sf32lb_get_sys_clk(config);
if (config->usb_div == 0U) {
return src;
}
return src / config->usb_div;
}
static int clock_control_sf32lb_rcc_on(const struct device *dev, clock_control_subsys_t sys)
{
const struct clock_control_sf32lb_rcc_config *config = dev->config;
uint16_t id = *(uint16_t *)sys;
sys_set_bit(config->base + FIELD_GET(SF32LB_CLOCK_OFFSET_MSK, id),
FIELD_GET(SF32LB_CLOCK_BIT_MSK, id));
return 0;
}
static int clock_control_sf32lb_rcc_off(const struct device *dev, clock_control_subsys_t sys)
{
const struct clock_control_sf32lb_rcc_config *config = dev->config;
uint16_t id = *(uint16_t *)sys;
sys_clear_bit(config->base + FIELD_GET(SF32LB_CLOCK_OFFSET_MSK, id),
FIELD_GET(SF32LB_CLOCK_BIT_MSK, id));
return 0;
}
int clock_control_sf32lb_rcc_get_rate(const struct device *dev, clock_control_subsys_t sys,
uint32_t *rate)
{
const struct clock_control_sf32lb_rcc_config *config = dev->config;
uint16_t id = *(uint16_t *)sys;
switch (id) {
case SF32LB52X_CLOCK_DMAC1:
case SF32LB52X_CLOCK_EXTDMA:
case SF32LB52X_CLOCK_EPIC:
case SF32LB52X_CLOCK_EZIP1:
case SF32LB52X_CLOCK_LCDC1:
case SF32LB52X_CLOCK_AES:
case SF32LB52X_CLOCK_SDMMC1:
case SF32LB52X_CLOCK_CRC1:
case SF32LB52X_CLOCK_SECU1:
*rate = sf32lb_get_hclk(config);
return 0;
case SF32LB52X_CLOCK_MPI1:
*rate = sf32lb_get_mpi_clk(config, config->mpi1_clk_src);
return 0;
case SF32LB52X_CLOCK_MPI2:
*rate = sf32lb_get_mpi_clk(config, config->mpi2_clk_src);
return 0;
case SF32LB52X_CLOCK_USBC:
*rate = sf32lb_get_usb_clk(config);
return 0;
case SF32LB52X_CLOCK_MAILBOX1:
case SF32LB52X_CLOCK_PINMUX1:
case SF32LB52X_CLOCK_SYSCFG1:
case SF32LB52X_CLOCK_GPIO1:
case SF32LB52X_CLOCK_PTC1:
case SF32LB52X_CLOCK_TRNG:
case SF32LB52X_CLOCK_EFUSEC:
case SF32LB52X_CLOCK_GPADC:
case SF32LB52X_CLOCK_TSEN:
case SF32LB52X_CLOCK_GPTIM1:
case SF32LB52X_CLOCK_ATIM1:
*rate = sf32lb_get_pclk1(config);
return 0;
case SF32LB52X_CLOCK_GPTIM2:
*rate = 24000000U;
return 0;
case SF32LB52X_CLOCK_BTIM1:
case SF32LB52X_CLOCK_BTIM2:
*rate = sf32lb_get_pclk1(config) / 2U;
return 0;
case SF32LB52X_CLOCK_I2C1:
case SF32LB52X_CLOCK_I2C2:
case SF32LB52X_CLOCK_I2C3:
case SF32LB52X_CLOCK_I2C4:
case SF32LB52X_CLOCK_SPI1:
case SF32LB52X_CLOCK_SPI2:
case SF32LB52X_CLOCK_USART2:
case SF32LB52X_CLOCK_USART3:
*rate = sf32lb_get_clk_peri(config);
return 0;
case SF32LB52X_CLOCK_I2S1:
case SF32LB52X_CLOCK_AUDPRC:
case SF32LB52X_CLOCK_AUDCODEC:
case SF32LB52X_CLOCK_PDM1:
*rate = config->hxt48_freq;
return 0;
default:
break;
}
return -ENOTSUP;
}
static enum clock_control_status clock_control_sf32lb_rcc_get_status(const struct device *dev,
clock_control_subsys_t sys)
{
const struct clock_control_sf32lb_rcc_config *config = dev->config;
uint16_t id = *(uint16_t *)sys;
if (sys_test_bit(config->base + FIELD_GET(SF32LB_CLOCK_OFFSET_MSK, id),
FIELD_GET(SF32LB_CLOCK_BIT_MSK, id)) != 0) {
return CLOCK_CONTROL_STATUS_ON;
}
return CLOCK_CONTROL_STATUS_OFF;
}
static DEVICE_API(clock_control, clock_control_sf32lb_rcc_api) = {
.on = clock_control_sf32lb_rcc_on,
.off = clock_control_sf32lb_rcc_off,
.get_rate = clock_control_sf32lb_rcc_get_rate,
.get_status = clock_control_sf32lb_rcc_get_status,
};
static int clock_control_sf32lb_rcc_init(const struct device *dev)
{
const struct clock_control_sf32lb_rcc_config *config = dev->config;
bool need_hxt48 = sf32lb_rcc_needs_hxt48(config);
uint32_t val;
int ret;
if (need_hxt48) {
if ((config->hxt48 == NULL) || !device_is_ready(config->hxt48)) {
return -ENODEV;
}
ret = clock_control_on(config->hxt48, NULL);
if (ret < 0) {
return ret;
}
}
if (config->dll1_freq != 0U || config->dll2_freq != 0U) {
val = sys_read32(config->pmuc + PMUC_HXT_CR1);
val |= PMUC_HXT_CR1_BUF_DLL_EN;
sys_write32(val, config->pmuc + PMUC_HXT_CR1);
val = sys_read32(config->cfg + HPSYS_CFG_CAU2_CR);
val |= HPSYS_CFG_CAU2_CR_HPBG_EN | HPSYS_CFG_CAU2_CR_HPBG_VDDPSW_EN;
sys_write32(val, config->cfg + HPSYS_CFG_CAU2_CR);
val = sys_read32(config->base + HPSYS_RCC_CSR);
val &= ~(HPSYS_RCC_CSR_SEL_SYS_Msk | HPSYS_RCC_CSR_SEL_PERI_Msk);
val |= FIELD_PREP(HPSYS_RCC_CSR_SEL_SYS_Msk, SF32LB_SYS_CLK_IDX_HXT48) |
FIELD_PREP(HPSYS_RCC_CSR_SEL_PERI_Msk, SF32LB_PERI_CLK_IDX_HXT48);
sys_write32(val, config->base + HPSYS_RCC_CSR);
if (config->dll1_freq != 0U) {
configure_dll(dev, config->dll1_freq, HPSYS_RCC_DLL1CR);
}
if (config->dll2_freq != 0U) {
configure_dll(dev, config->dll2_freq, HPSYS_RCC_DLL2CR);
}
}
/* configure HDIV/PDIV1/PDIV2 dividers */
val = sys_read32(config->base + HPSYS_RCC_CFGR);
val &= ~(HPSYS_RCC_CFGR_HDIV_Msk | HPSYS_RCC_CFGR_PDIV1_Msk | HPSYS_RCC_CFGR_PDIV2_Msk);
val |= FIELD_PREP(HPSYS_RCC_CFGR_HDIV_Msk, config->hdiv) |
FIELD_PREP(HPSYS_RCC_CFGR_PDIV1_Msk, config->pdiv1) |
FIELD_PREP(HPSYS_RCC_CFGR_PDIV2_Msk, config->pdiv2);
sys_write32(val, config->base + HPSYS_RCC_CFGR);
val = sys_read32(config->base + HPSYS_RCC_CSR);
val &= ~(HPSYS_RCC_CSR_SEL_SYS_Msk | HPSYS_RCC_CSR_SEL_PERI_Msk |
HPSYS_RCC_CSR_SEL_MPI1_Msk | HPSYS_RCC_CSR_SEL_MPI2_Msk |
HPSYS_RCC_CSR_SEL_USBC_Msk);
val |= FIELD_PREP(HPSYS_RCC_CSR_SEL_SYS_Msk, config->sys_clk_src) |
FIELD_PREP(HPSYS_RCC_CSR_SEL_PERI_Msk, config->peri_clk_src) |
FIELD_PREP(HPSYS_RCC_CSR_SEL_MPI1_Msk, config->mpi1_clk_src) |
FIELD_PREP(HPSYS_RCC_CSR_SEL_MPI2_Msk, config->mpi2_clk_src) |
FIELD_PREP(HPSYS_RCC_CSR_SEL_USBC_Msk, config->usb_clk_src);
sys_write32(val, config->base + HPSYS_RCC_CSR);
val = FIELD_PREP(HPSYS_RCC_USBCR_DIV_Msk, config->usb_div);
sys_write32(val, config->base + HPSYS_RCC_USBCR);
return 0;
}
/* DLL1/2 requires HXT48 */
IF_ENABLED(UTIL_OR(
DT_NODE_HAS_STATUS(DT_INST_CHILD(0, dll1), okay),
DT_NODE_HAS_STATUS(DT_INST_CHILD(0, dll2), okay)),
(BUILD_ASSERT(
(DT_NODE_HAS_STATUS(DT_INST_CLOCKS_CTLR_BY_NAME(0, hxt48), okay)),
"DLL1/2 require HXT48 to be enabled");))
/* DLL1/2 frequency must be a multiple of step size */
IF_ENABLED(DT_NODE_HAS_STATUS(DT_INST_CHILD(0, dll1), okay), (
BUILD_ASSERT(
((DT_PROP(DT_INST_CHILD(0, dll1), clock_frequency) != 0) &&
((DT_PROP(DT_INST_CHILD(0, dll1), clock_frequency) %
HPSYS_RCC_DLLXCR_STG_STEP) == 0)),
"DLL1 frequency must be a non-zero multiple of "
STRINGIFY(HPSYS_RCC_DLLXCR_STG_STEP)
);))
IF_ENABLED(DT_NODE_HAS_STATUS(DT_INST_CHILD(0, dll2), okay), (
BUILD_ASSERT(
((DT_PROP(DT_INST_CHILD(0, dll2), clock_frequency) != 0) &&
((DT_PROP(DT_INST_CHILD(0, dll2), clock_frequency) %
HPSYS_RCC_DLLXCR_STG_STEP) == 0)),
"DLL2 frequency must be a non-zero multiple of "
STRINGIFY(HPSYS_RCC_DLLXCR_STG_STEP)
);))
BUILD_ASSERT(!SF32LB_RCC_NEEDS_HXT48(0) ||
DT_NODE_HAS_STATUS(DT_INST_CLOCKS_CTLR_BY_NAME(0, hxt48), okay),
"HXT48 clock must be enabled when selected or when DLLs are used");
BUILD_ASSERT(!SF32LB_SYS_CLK_REQUIRES_DLL1(0) || DT_NODE_HAS_STATUS(DT_INST_CHILD(0, dll1), okay),
"DLL1 system clock selection requires the dll1 node to be enabled");
BUILD_ASSERT(!SF32LB_MPI1_CLK_REQUIRES_DLL2(0) || DT_NODE_HAS_STATUS(DT_INST_CHILD(0, dll2), okay),
"MPI1 clock selection requires the dll2 node to be enabled when set to DLL2");
BUILD_ASSERT(!SF32LB_MPI1_CLK_REQUIRES_DLL1(0) || DT_NODE_HAS_STATUS(DT_INST_CHILD(0, dll1), okay),
"MPI1 clock selection requires the dll1 node to be enabled when set to DLL1");
BUILD_ASSERT(!SF32LB_MPI2_CLK_REQUIRES_DLL2(0) || DT_NODE_HAS_STATUS(DT_INST_CHILD(0, dll2), okay),
"MPI2 clock selection requires the dll2 node to be enabled when set to DLL2");
BUILD_ASSERT(!SF32LB_MPI2_CLK_REQUIRES_DLL1(0) || DT_NODE_HAS_STATUS(DT_INST_CHILD(0, dll1), okay),
"MPI2 clock selection requires the dll1 node to be enabled when set to DLL1");
BUILD_ASSERT(IN_RANGE(SF32LB_USB_DIV_VALUE(0), 1, 7),
"USB clock divider must be in the range [1, 7]");
BUILD_ASSERT(!SF32LB_USB_CLK_REQUIRES_DLL2(0) || DT_NODE_HAS_STATUS(DT_INST_CHILD(0, dll2), okay),
"USB clock selection requires the dll2 node to be enabled when set to DLL2");
static const struct clock_control_sf32lb_rcc_config config = {
.base = DT_REG_ADDR(DT_INST_PARENT(0)),
.cfg = DT_REG_ADDR(DT_INST_PHANDLE(0, sifli_cfg)),
.pmuc = DT_REG_ADDR(DT_INST_PHANDLE(0, sifli_pmuc)),
.hxt48 = DEVICE_DT_GET_OR_NULL(DT_INST_CLOCKS_CTLR_BY_NAME(0, hxt48)),
.hdiv = DT_INST_PROP(0, sifli_hdiv),
.pdiv1 = DT_INST_PROP(0, sifli_pdiv1),
.pdiv2 = DT_INST_PROP(0, sifli_pdiv2),
.sys_clk_src = SF32LB_SYS_CLK_SRC_VALUE(0),
.peri_clk_src = SF32LB_PERI_CLK_SRC_VALUE(0),
.mpi1_clk_src = SF32LB_MPI1_CLK_SRC_VALUE(0),
.mpi2_clk_src = SF32LB_MPI2_CLK_SRC_VALUE(0),
.usb_clk_src = SF32LB_USB_CLK_SRC_VALUE(0),
.usb_div = SF32LB_USB_DIV_VALUE(0),
.sys_clk_freq = SF32LB_SYS_CLK_FREQ(0),
.peri_clk_freq = SF32LB_PERI_CLK_FREQ(0),
.hrc48_freq = SF32LB_CLOCK_FREQ_BY_NAME(0, hrc48),
.hxt48_freq = SF32LB_CLOCK_FREQ_BY_NAME(0, hxt48),
.lrc32_freq = SF32LB_CLOCK_FREQ_BY_NAME(0, lrc32),
.lrc10_freq = SF32LB_CLOCK_FREQ_BY_NAME(0, lrc10),
.lxt32_freq = SF32LB_CLOCK_FREQ_BY_NAME(0, lxt32),
.dll1_freq = COND_CODE_1(DT_NODE_HAS_STATUS(DT_INST_CHILD(0, dll1), okay),
(DT_PROP(DT_INST_CHILD(0, dll1), clock_frequency)), (0U)),
.dll2_freq = COND_CODE_1(DT_NODE_HAS_STATUS(DT_INST_CHILD(0, dll2), okay),
(DT_PROP(DT_INST_CHILD(0, dll2), clock_frequency)), (0U)),
};
DEVICE_DT_INST_DEFINE(0, clock_control_sf32lb_rcc_init, NULL, NULL, &config, PRE_KERNEL_1,
CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &clock_control_sf32lb_rcc_api);