All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kever Yang <kever.yang@rock-chips.com>
To: Elaine Zhang <zhangqing@rock-chips.com>, sjg@chromium.org, lukma@denx.de
Cc: u-boot@lists.denx.de, chenjh@rock-chips.com,
	Elaine Zhang <zhangqing@rock-chips.com>
Subject: Re: [PATCH v1 2/2] rockchip: rk3568: add clock driver
Date: Fri, 21 May 2021 21:33:57 +0800	[thread overview]
Message-ID: <d005043a-72ec-f3c2-3dc6-3f592203bf3a@rock-chips.com> (raw)
In-Reply-To: <20210519084919.11475-3-zhangqing@rock-chips.com>

Hi Elaine,

     Thanks for your patch, pls update the copyright info and remove 
unused clock set/get.

On 2021/5/19 下午4:49, Elaine Zhang wrote:
> From: Elaine Zhang <zhangqing@rock-chips.com>
>
> Add rk3568 clock driver and cru structure definition.
>
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> ---
>   .../include/asm/arch-rockchip/cru_rk3568.h    |  504 +++
>   drivers/clk/rockchip/Makefile                 |    1 +
>   drivers/clk/rockchip/clk_rk3568.c             | 2908 +++++++++++++++++
>   3 files changed, 3413 insertions(+)
>   create mode 100644 arch/arm/include/asm/arch-rockchip/cru_rk3568.h
>   create mode 100644 drivers/clk/rockchip/clk_rk3568.c
>
> diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3568.h b/arch/arm/include/asm/arch-rockchip/cru_rk3568.h
> new file mode 100644
> index 000000000000..6c59033f03a6
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-rockchip/cru_rk3568.h
> @@ -0,0 +1,504 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
> + * Author: Elaine Zhang <zhangqing@rock-chips.com>
> + */
> +
> +#ifndef _ASM_ARCH_CRU_RK3568_H
> +#define _ASM_ARCH_CRU_RK3568_H
> +
> +#define MHz		1000000
> +#define KHz		1000
> +#define OSC_HZ		(24 * MHz)
> +
> +#define APLL_HZ		(816 * MHz)
> +#define GPLL_HZ		(1188 * MHz)
> +#define CPLL_HZ		(1000 * MHz)
> +#define PPLL_HZ		(100 * MHz)
> +
> +/* RK3568 pll id */
> +enum rk3568_pll_id {
> +	APLL,
> +	DPLL,
> +	CPLL,
> +	GPLL,
> +	NPLL,
> +	VPLL,
> +	PPLL,
> +	HPLL,
> +	PLL_COUNT,
> +};
> +
> +struct rk3568_clk_info {
> +	unsigned long id;
> +	char *name;
> +	bool is_cru;
> +};
> +
> +/* Private data for the clock driver - used by rockchip_get_cru() */
> +struct rk3568_pmuclk_priv {
> +	struct rk3568_pmucru *pmucru;
> +	ulong ppll_hz;
> +	ulong hpll_hz;
> +};
> +
> +struct rk3568_clk_priv {
> +	struct rk3568_cru *cru;
> +	struct rk3568_grf *grf;
> +	ulong ppll_hz;
> +	ulong hpll_hz;
> +	ulong gpll_hz;
> +	ulong cpll_hz;
> +	ulong npll_hz;
> +	ulong vpll_hz;
> +	ulong armclk_hz;
> +	ulong armclk_enter_hz;
> +	ulong armclk_init_hz;
> +	bool sync_kernel;
> +	bool set_armclk_rate;
> +};
> +
> +struct rk3568_pll {
> +	unsigned int con0;
> +	unsigned int con1;
> +	unsigned int con2;
> +	unsigned int con3;
> +	unsigned int con4;
> +	unsigned int reserved0[3];
> +};
> +
> +struct rk3568_pmucru {
> +	struct rk3568_pll pll[2];/* Address Offset: 0x0000 */
> +	unsigned int reserved0[16];/* Address Offset: 0x0040 */
> +	unsigned int mode_con00;/* Address Offset: 0x0080 */
> +	unsigned int reserved1[31];/* Address Offset: 0x0084 */
> +	unsigned int pmu_clksel_con[10];/* Address Offset: 0x0100 */
> +	unsigned int reserved2[22];/* Address Offset: 0x0128 */
> +	unsigned int pmu_clkgate_con[3];/* Address Offset: 0x0180 */
> +	unsigned int reserved3[29];/* Address Offset: 0x018C */
> +	unsigned int pmu_softrst_con[1];/* Address Offset: 0x0200 */
> +};
> +
> +check_member(rk3568_pmucru, mode_con00, 0x80);
> +check_member(rk3568_pmucru, pmu_softrst_con[0], 0x200);
> +
> +struct rk3568_cru {
> +	struct rk3568_pll pll[6];
> +	unsigned int mode_con00;/* Address Offset: 0x00C0 */
> +	unsigned int misc_con[3];/* Address Offset: 0x00C4 */
> +	unsigned int glb_cnt_th;/* Address Offset: 0x00D0 */
> +	unsigned int glb_srst_fst;/* Address Offset: 0x00D4 */
> +	unsigned int glb_srsr_snd; /* Address Offset: 0x00D8 */
> +	unsigned int glb_rst_con;/* Address Offset: 0x00DC */
> +	unsigned int glb_rst_st;/* Address Offset: 0x00E0 */
> +	unsigned int reserved0[7];/* Address Offset: 0x00E4 */
> +	unsigned int clksel_con[85]; /* Address Offset: 0x0100 */
> +	unsigned int reserved1[43];/* Address Offset: 0x0254 */
> +	unsigned int clkgate_con[36];/* Address Offset: 0x0300 */
> +	unsigned int reserved2[28]; /* Address Offset: 0x0390 */
> +	unsigned int softrst_con[30];/* Address Offset: 0x0400 */
> +	unsigned int reserved3[2];/* Address Offset: 0x0478 */
> +	unsigned int ssgtbl[32];/* Address Offset: 0x0480 */
> +	unsigned int reserved4[32];/* Address Offset: 0x0500 */
> +	unsigned int sdmmc0_con[2];/* Address Offset: 0x0580 */
> +	unsigned int sdmmc1_con[2];/* Address Offset: 0x058C */
> +	unsigned int sdmmc2_con[2];/* Address Offset: 0x0590 */
> +	unsigned int emmc_con[2];/* Address Offset: 0x0598 */
> +};
> +
> +check_member(rk3568_cru, mode_con00, 0xc0);
> +check_member(rk3568_cru, softrst_con[0], 0x400);
> +
> +struct pll_rate_table {
> +	unsigned long rate;
> +	unsigned int fbdiv;
> +	unsigned int postdiv1;
> +	unsigned int refdiv;
> +	unsigned int postdiv2;
> +	unsigned int dsmpd;
> +	unsigned int frac;
> +};
> +
> +#define RK3568_PMU_MODE			0x80
> +#define RK3568_PMU_PLL_CON(x)		((x) * 0x4)
> +#define RK3568_PLL_CON(x)		((x) * 0x4)
> +#define RK3568_MODE_CON			0xc0
> +
> +enum {
> +	/* CRU_PMU_CLK_SEL0_CON */
> +	RTC32K_SEL_SHIFT		= 6,
> +	RTC32K_SEL_MASK			= 0x3 << RTC32K_SEL_SHIFT,
> +	RTC32K_SEL_PMUPVTM		= 0,
> +	RTC32K_SEL_OSC1_32K,
> +	RTC32K_SEL_OSC0_DIV32K,
> +
> +	/* CRU_PMU_CLK_SEL1_CON */
> +	RTC32K_FRAC_NUMERATOR_SHIFT	= 16,
> +	RTC32K_FRAC_NUMERATOR_MASK	= 0xffff << 16,
> +	RTC32K_FRAC_DENOMINATOR_SHIFT	= 0,
> +	RTC32K_FRAC_DENOMINATOR_MASK	= 0xffff,
> +
> +	/* CRU_PMU_CLK_SEL2_CON */
> +	PCLK_PDPMU_SEL_SHIFT		= 15,
> +	PCLK_PDPMU_SEL_MASK		= 1 << PCLK_PDPMU_SEL_SHIFT,
> +	PCLK_PDPMU_SEL_PPLL		= 0,
> +	PCLK_PDPMU_SEL_GPLL,
> +	PCLK_PDPMU_DIV_SHIFT		= 0,
> +	PCLK_PDPMU_DIV_MASK		= 0x1f,
> +
> +	/* CRU_PMU_CLK_SEL3_CON */
> +	CLK_I2C0_DIV_SHIFT		= 0,
> +	CLK_I2C0_DIV_MASK		= 0x7f,
> +
> +	/* CRU_PMU_CLK_SEL6_CON */
> +	CLK_PWM0_SEL_SHIFT		= 7,
> +	CLK_PWM0_SEL_MASK		= 1 << CLK_PWM0_SEL_SHIFT,
> +	CLK_PWM0_SEL_XIN24M		= 0,
> +	CLK_PWM0_SEL_PPLL,
> +	CLK_PWM0_DIV_SHIFT		= 0,
> +	CLK_PWM0_DIV_MASK		= 0x7f,
> +
> +	/* CRU_CLK_SEL0_CON */
> +	CLK_CORE_PRE_SEL_SHIFT		= 7,
> +	CLK_CORE_PRE_SEL_MASK		= 1 << CLK_CORE_PRE_SEL_SHIFT,
> +	CLK_CORE_PRE_SEL_SRC		= 0,
> +	CLK_CORE_PRE_SEL_APLL,
> +
> +	/* CRU_CLK_SEL2_CON */
> +	SCLK_CORE_PRE_SEL_SHIFT		= 15,
> +	SCLK_CORE_PRE_SEL_MASK		= 1 << SCLK_CORE_PRE_SEL_SHIFT,
> +	SCLK_CORE_PRE_SEL_SRC		= 0,
> +	SCLK_CORE_PRE_SEL_NPLL,
> +	SCLK_CORE_SRC_SEL_SHIFT		= 8,
> +	SCLK_CORE_SRC_SEL_MASK		= 3 << SCLK_CORE_SRC_SEL_SHIFT,
> +	SCLK_CORE_SRC_SEL_APLL		= 0,
> +	SCLK_CORE_SRC_SEL_GPLL,
> +	SCLK_CORE_SRC_SEL_NPLL,
> +	SCLK_CORE_SRC_DIV_SHIFT		= 0,
> +	SCLK_CORE_SRC_DIV_MASK		= 0x1f << SCLK_CORE_SRC_DIV_SHIFT,
> +
> +	/* CRU_CLK_SEL3_CON */
> +	GICCLK_CORE_DIV_SHIFT		= 8,
> +	GICCLK_CORE_DIV_MASK		= 0x1f << GICCLK_CORE_DIV_SHIFT,
> +	ATCLK_CORE_DIV_SHIFT		= 0,
> +	ATCLK_CORE_DIV_MASK		= 0x1f << ATCLK_CORE_DIV_SHIFT,
> +
> +	/* CRU_CLK_SEL4_CON */
> +	PERIPHCLK_CORE_PRE_DIV_SHIFT	= 8,
> +	PERIPHCLK_CORE_PRE_DIV_MASK	= 0x1f << PERIPHCLK_CORE_PRE_DIV_SHIFT,
> +	PCLK_CORE_PRE_DIV_SHIFT		= 0,
> +	PCLK_CORE_PRE_DIV_MASK		= 0x1f << PCLK_CORE_PRE_DIV_SHIFT,
> +
> +	/* CRU_CLK_SEL5_CON */
> +	ACLK_CORE_NIU2BUS_SEL_SHIFT	= 14,
> +	ACLK_CORE_NIU2BUS_SEL_MASK	= 0x3 << ACLK_CORE_NIU2BUS_SEL_SHIFT,
> +	ACLK_CORE_NDFT_DIV_SHIFT	= 8,
> +	ACLK_CORE_NDFT_DIV_MASK		= 0x1f << ACLK_CORE_NDFT_DIV_SHIFT,
> +
> +	/* CRU_CLK_SEL10_CON */
> +	HCLK_PERIMID_SEL_SHIFT		= 6,
> +	HCLK_PERIMID_SEL_MASK		= 3 << HCLK_PERIMID_SEL_SHIFT,
> +	HCLK_PERIMID_SEL_150M		= 0,
> +	HCLK_PERIMID_SEL_100M,
> +	HCLK_PERIMID_SEL_75M,
> +	HCLK_PERIMID_SEL_24M,
> +	ACLK_PERIMID_SEL_SHIFT		= 4,
> +	ACLK_PERIMID_SEL_MASK		= 3 << ACLK_PERIMID_SEL_SHIFT,
> +	ACLK_PERIMID_SEL_300M		= 0,
> +	ACLK_PERIMID_SEL_200M,
> +	ACLK_PERIMID_SEL_100M,
> +	ACLK_PERIMID_SEL_24M,
> +
> +	/* CRU_CLK_SEL27_CON */
> +	CLK_CRYPTO_PKA_SEL_SHIFT	= 6,
> +	CLK_CRYPTO_PKA_SEL_MASK		= 3 << CLK_CRYPTO_PKA_SEL_SHIFT,
> +	CLK_CRYPTO_PKA_SEL_300M		= 0,
> +	CLK_CRYPTO_PKA_SEL_200M,
> +	CLK_CRYPTO_PKA_SEL_100M,
> +	CLK_CRYPTO_CORE_SEL_SHIFT	= 4,
> +	CLK_CRYPTO_CORE_SEL_MASK	= 3 << CLK_CRYPTO_CORE_SEL_SHIFT,
> +	CLK_CRYPTO_CORE_SEL_200M	= 0,
> +	CLK_CRYPTO_CORE_SEL_150M,
> +	CLK_CRYPTO_CORE_SEL_100M,
> +	HCLK_SECURE_FLASH_SEL_SHIFT	= 2,
> +	HCLK_SECURE_FLASH_SEL_MASK	= 3 << HCLK_SECURE_FLASH_SEL_SHIFT,
> +	HCLK_SECURE_FLASH_SEL_150M	= 0,
> +	HCLK_SECURE_FLASH_SEL_100M,
> +	HCLK_SECURE_FLASH_SEL_75M,
> +	HCLK_SECURE_FLASH_SEL_24M,
> +	ACLK_SECURE_FLASH_SEL_SHIFT	= 0,
> +	ACLK_SECURE_FLASH_SEL_MASK	= 3 << ACLK_SECURE_FLASH_SEL_SHIFT,
> +	ACLK_SECURE_FLASH_SEL_200M	= 0,
> +	ACLK_SECURE_FLASH_SEL_150M,
> +	ACLK_SECURE_FLASH_SEL_100M,
> +	ACLK_SECURE_FLASH_SEL_24M,
> +
> +	/* CRU_CLK_SEL28_CON */
> +	CCLK_EMMC_SEL_SHIFT		= 12,
> +	CCLK_EMMC_SEL_MASK		= 7 << CCLK_EMMC_SEL_SHIFT,
> +	CCLK_EMMC_SEL_24M		= 0,
> +	CCLK_EMMC_SEL_200M,
> +	CCLK_EMMC_SEL_150M,
> +	CCLK_EMMC_SEL_100M,
> +	CCLK_EMMC_SEL_50M,
> +	CCLK_EMMC_SEL_375K,
> +	BCLK_EMMC_SEL_SHIFT		= 8,
> +	BCLK_EMMC_SEL_MASK		= 3 << BCLK_EMMC_SEL_SHIFT,
> +	BCLK_EMMC_SEL_200M		= 0,
> +	BCLK_EMMC_SEL_150M,
> +	BCLK_EMMC_SEL_125M,
> +	SCLK_SFC_SEL_SHIFT		= 4,
> +	SCLK_SFC_SEL_MASK		= 7 << SCLK_SFC_SEL_SHIFT,
> +	SCLK_SFC_SEL_24M		= 0,
> +	SCLK_SFC_SEL_50M,
> +	SCLK_SFC_SEL_75M,
> +	SCLK_SFC_SEL_100M,
> +	SCLK_SFC_SEL_125M,
> +	SCLK_SFC_SEL_150M,
> +	NCLK_NANDC_SEL_SHIFT		= 0,
> +	NCLK_NANDC_SEL_MASK		= 3 << NCLK_NANDC_SEL_SHIFT,
> +	NCLK_NANDC_SEL_200M		= 0,
> +	NCLK_NANDC_SEL_150M,
> +	NCLK_NANDC_SEL_100M,
> +	NCLK_NANDC_SEL_24M,
> +
> +	/* CRU_CLK_SEL30_CON */
> +	CLK_SDMMC1_SEL_SHIFT		= 12,
> +	CLK_SDMMC1_SEL_MASK		= 7 << CLK_SDMMC1_SEL_SHIFT,
> +	CLK_SDMMC0_SEL_SHIFT		= 8,
> +	CLK_SDMMC0_SEL_MASK		= 7 << CLK_SDMMC0_SEL_SHIFT,
> +	CLK_SDMMC_SEL_24M		= 0,
> +	CLK_SDMMC_SEL_400M,
> +	CLK_SDMMC_SEL_300M,
> +	CLK_SDMMC_SEL_100M,
> +	CLK_SDMMC_SEL_50M,
> +	CLK_SDMMC_SEL_750K,
> +
> +	/* CRU_CLK_SEL31_CON */
> +	CLK_MAC0_OUT_SEL_SHIFT		= 14,
> +	CLK_MAC0_OUT_SEL_MASK		= 3 << CLK_MAC0_OUT_SEL_SHIFT,
> +	CLK_MAC0_OUT_SEL_125M		= 0,
> +	CLK_MAC0_OUT_SEL_50M,
> +	CLK_MAC0_OUT_SEL_25M,
> +	CLK_MAC0_OUT_SEL_24M,
> +	CLK_GMAC0_PTP_REF_SEL_SHIFT	= 12,
> +	CLK_GMAC0_PTP_REF_SEL_MASK	= 3 << CLK_GMAC0_PTP_REF_SEL_SHIFT,
> +	CLK_GMAC0_PTP_REF_SEL_62_5M	= 0,
> +	CLK_GMAC0_PTP_REF_SEL_100M,
> +	CLK_GMAC0_PTP_REF_SEL_50M,
> +	CLK_GMAC0_PTP_REF_SEL_24M,
> +	CLK_MAC0_2TOP_SEL_SHIFT		= 8,
> +	CLK_MAC0_2TOP_SEL_MASK		= 3 << CLK_MAC0_2TOP_SEL_SHIFT,
> +	CLK_MAC0_2TOP_SEL_125M		= 0,
> +	CLK_MAC0_2TOP_SEL_50M,
> +	CLK_MAC0_2TOP_SEL_25M,
> +	CLK_MAC0_2TOP_SEL_PPLL,
> +	RGMII0_CLK_SEL_SHIFT		= 4,
> +	RGMII0_CLK_SEL_MASK		= 3 << RGMII0_CLK_SEL_SHIFT,
> +	RGMII0_CLK_SEL_125M		= 0,
> +	RGMII0_CLK_SEL_125M_1,
> +	RGMII0_CLK_SEL_2_5M,
> +	RGMII0_CLK_SEL_25M,
> +	RMII0_CLK_SEL_SHIFT		= 3,
> +	RMII0_CLK_SEL_MASK		= 1 << RMII0_CLK_SEL_SHIFT,
> +	RMII0_CLK_SEL_2_5M		= 0,
> +	RMII0_CLK_SEL_25M,
> +	RMII0_EXTCLK_SEL_SHIFT		= 2,
> +	RMII0_EXTCLK_SEL_MASK		= 1 << RMII0_EXTCLK_SEL_SHIFT,
> +	RMII0_EXTCLK_SEL_MAC0_TOP	= 0,
> +	RMII0_EXTCLK_SEL_IO,
> +	RMII0_MODE_SHIFT		= 0,
> +	RMII0_MODE_MASK			= 3 << RMII0_MODE_SHIFT,
> +	RMII0_MODE_SEL_RGMII		= 0,
> +	RMII0_MODE_SEL_RMII,
> +	RMII0_MODE_SEL_GMII,
> +
> +	/* CRU_CLK_SEL32_CON */
> +	CLK_SDMMC2_SEL_SHIFT		= 8,
> +	CLK_SDMMC2_SEL_MASK		= 7 << CLK_SDMMC2_SEL_SHIFT,
> +
> +	/* CRU_CLK_SEL38_CON */
> +	ACLK_VOP_PRE_SEL_SHIFT		= 6,
> +	ACLK_VOP_PRE_SEL_MASK		= 3 << ACLK_VOP_PRE_SEL_SHIFT,
> +	ACLK_VOP_PRE_SEL_CPLL		= 0,
> +	ACLK_VOP_PRE_SEL_GPLL,
> +	ACLK_VOP_PRE_SEL_HPLL,
> +	ACLK_VOP_PRE_SEL_VPLL,
> +	ACLK_VOP_PRE_DIV_SHIFT		= 0,
> +	ACLK_VOP_PRE_DIV_MASK		= 0x1f << ACLK_VOP_PRE_DIV_SHIFT,
> +
> +	/* CRU_CLK_SEL39_CON */
> +	DCLK0_VOP_SEL_SHIFT		= 10,
> +	DCLK0_VOP_SEL_MASK		= 3 << DCLK0_VOP_SEL_SHIFT,
> +	DCLK_VOP_SEL_HPLL		= 0,
> +	DCLK_VOP_SEL_VPLL,
> +	DCLK_VOP_SEL_GPLL,
> +	DCLK_VOP_SEL_CPLL,
> +	DCLK0_VOP_DIV_SHIFT		= 0,
> +	DCLK0_VOP_DIV_MASK		= 0xff << DCLK0_VOP_DIV_SHIFT,
> +
> +	/* CRU_CLK_SEL40_CON */
> +	DCLK1_VOP_SEL_SHIFT		= 10,
> +	DCLK1_VOP_SEL_MASK		= 3 << DCLK1_VOP_SEL_SHIFT,
> +	DCLK1_VOP_DIV_SHIFT		= 0,
> +	DCLK1_VOP_DIV_MASK		= 0xff << DCLK1_VOP_DIV_SHIFT,
> +
> +	/* CRU_CLK_SEL41_CON */
> +	DCLK2_VOP_SEL_SHIFT		= 10,
> +	DCLK2_VOP_SEL_MASK		= 3 << DCLK2_VOP_SEL_SHIFT,
> +	DCLK2_VOP_DIV_SHIFT		= 0,
> +	DCLK2_VOP_DIV_MASK		= 0xff << DCLK2_VOP_DIV_SHIFT,
> +
> +	/* CRU_CLK_SEL43_CON */
> +	DCLK_EBC_SEL_SHIFT		= 6,
> +	DCLK_EBC_SEL_MASK		= 3 << DCLK_EBC_SEL_SHIFT,
> +	DCLK_EBC_SEL_GPLL_400M		= 0,
> +	DCLK_EBC_SEL_CPLL_333M,
> +	DCLK_EBC_SEL_GPLL_200M,
> +
> +	/* CRU_CLK_SEL47_CON */
> +	ACLK_RKVDEC_SEL_SHIFT		= 7,
> +	ACLK_RKVDEC_SEL_MASK		= 1 << ACLK_RKVDEC_SEL_SHIFT,
> +	ACLK_RKVDEC_SEL_GPLL		= 0,
> +	ACLK_RKVDEC_SEL_CPLL,
> +	ACLK_RKVDEC_DIV_SHIFT		= 0,
> +	ACLK_RKVDEC_DIV_MASK		= 0x1f << ACLK_RKVDEC_DIV_SHIFT,
> +
> +	/* CRU_CLK_SEL49_CON */
> +	CLK_RKVDEC_CORE_SEL_SHIFT	= 14,
> +	CLK_RKVDEC_CORE_SEL_MASK	= 0x3 << CLK_RKVDEC_CORE_SEL_SHIFT,
> +	CLK_RKVDEC_CORE_SEL_GPLL	= 0,
> +	CLK_RKVDEC_CORE_SEL_CPLL,
> +	CLK_RKVDEC_CORE_SEL_NPLL,
> +	CLK_RKVDEC_CORE_SEL_VPLL,
> +	CLK_RKVDEC_CORE_DIV_SHIFT	= 8,
> +	CLK_RKVDEC_CORE_DIV_MASK	= 0x1f << CLK_RKVDEC_CORE_DIV_SHIFT,
> +
> +	/* CRU_CLK_SEL50_CON */
> +	PCLK_BUS_SEL_SHIFT		= 4,
> +	PCLK_BUS_SEL_MASK		= 3 << PCLK_BUS_SEL_SHIFT,
> +	PCLK_BUS_SEL_100M		= 0,
> +	PCLK_BUS_SEL_75M,
> +	PCLK_BUS_SEL_50M,
> +	PCLK_BUS_SEL_24M,
> +	ACLK_BUS_SEL_SHIFT		= 0,
> +	ACLK_BUS_SEL_MASK		= 3 << ACLK_BUS_SEL_SHIFT,
> +	ACLK_BUS_SEL_200M		= 0,
> +	ACLK_BUS_SEL_150M,
> +	ACLK_BUS_SEL_100M,
> +	ACLK_BUS_SEL_24M,
> +
> +	/* CRU_CLK_SEL51_CON */
> +	CLK_TSADC_DIV_SHIFT		= 8,
> +	CLK_TSADC_DIV_MASK		= 0x7f << CLK_TSADC_DIV_SHIFT,
> +	CLK_TSADC_TSEN_SEL_SHIFT	= 4,
> +	CLK_TSADC_TSEN_SEL_MASK		= 0x3 << CLK_TSADC_TSEN_SEL_SHIFT,
> +	CLK_TSADC_TSEN_SEL_24M		= 0,
> +	CLK_TSADC_TSEN_SEL_100M,
> +	CLK_TSADC_TSEN_SEL_CPLL_100M,
> +	CLK_TSADC_TSEN_DIV_SHIFT	= 0,
> +	CLK_TSADC_TSEN_DIV_MASK		= 0x7 << CLK_TSADC_TSEN_DIV_SHIFT,
> +
> +	/* CRU_CLK_SEL52_CON */
> +	CLK_UART_SEL_SHIFT		= 12,
> +	CLK_UART_SEL_MASK		= 0x3 << CLK_UART_SEL_SHIFT,
> +	CLK_UART_SEL_SRC		= 0,
> +	CLK_UART_SEL_FRAC,
> +	CLK_UART_SEL_XIN24M,
> +	CLK_UART_SRC_SEL_SHIFT		= 8,
> +	CLK_UART_SRC_SEL_MASK		= 0x3 << CLK_UART_SRC_SEL_SHIFT,
> +	CLK_UART_SRC_SEL_GPLL		= 0,
> +	CLK_UART_SRC_SEL_CPLL,
> +	CLK_UART_SRC_SEL_480M,
> +	CLK_UART_SRC_DIV_SHIFT		= 0,
> +	CLK_UART_SRC_DIV_MASK		= 0x3f << CLK_UART_SRC_DIV_SHIFT,
> +
> +	/* CRU_CLK_SEL53_CON */
> +	CLK_UART_FRAC_NUMERATOR_SHIFT	= 16,
> +	CLK_UART_FRAC_NUMERATOR_MASK	= 0xffff << 16,
> +	CLK_UART_FRAC_DENOMINATOR_SHIFT	= 0,
> +	CLK_UART_FRAC_DENOMINATOR_MASK	= 0xffff,
> +
> +	/* CRU_CLK_SEL71_CON */
> +	CLK_I2C_SEL_SHIFT		= 8,
> +	CLK_I2C_SEL_MASK		= 3 << CLK_I2C_SEL_SHIFT,
> +	CLK_I2C_SEL_200M		= 0,
> +	CLK_I2C_SEL_100M,
> +	CLK_I2C_SEL_24M,
> +	CLK_I2C_SEL_CPLL_100M,
> +
> +	/* CRU_CLK_SEL72_CON */
> +	CLK_PWM3_SEL_SHIFT		= 12,
> +	CLK_PWM3_SEL_MASK		= 3 << CLK_PWM3_SEL_SHIFT,
> +	CLK_PWM2_SEL_SHIFT		= 10,
> +	CLK_PWM2_SEL_MASK		= 3 << CLK_PWM2_SEL_SHIFT,
> +	CLK_PWM1_SEL_SHIFT		= 8,
> +	CLK_PWM1_SEL_MASK		= 3 << CLK_PWM1_SEL_SHIFT,
> +	CLK_PWM_SEL_100M		= 0,
> +	CLK_PWM_SEL_24M,
> +	CLK_PWM_SEL_CPLL_100M,
> +	CLK_SPI3_SEL_SHIFT		= 6,
> +	CLK_SPI3_SEL_MASK		= 3 << CLK_SPI3_SEL_SHIFT,
> +	CLK_SPI2_SEL_SHIFT		= 4,
> +	CLK_SPI2_SEL_MASK		= 3 << CLK_SPI2_SEL_SHIFT,
> +	CLK_SPI1_SEL_SHIFT		= 2,
> +	CLK_SPI1_SEL_MASK		= 3 << CLK_SPI1_SEL_SHIFT,
> +	CLK_SPI0_SEL_SHIFT		= 0,
> +	CLK_SPI0_SEL_MASK		= 3 << CLK_SPI0_SEL_SHIFT,
> +	CLK_SPI_SEL_200M		= 0,
> +	CLK_SPI_SEL_24M,
> +	CLK_SPI_SEL_CPLL_100M,
> +
> +	/* CRU_CLK_SEL73_CON */
> +	PCLK_TOP_SEL_SHIFT		= 12,
> +	PCLK_TOP_SEL_MASK		= 3 << PCLK_TOP_SEL_SHIFT,
> +	PCLK_TOP_SEL_100M		= 0,
> +	PCLK_TOP_SEL_75M,
> +	PCLK_TOP_SEL_50M,
> +	PCLK_TOP_SEL_24M,
> +	HCLK_TOP_SEL_SHIFT		= 8,
> +	HCLK_TOP_SEL_MASK		= 3 << HCLK_TOP_SEL_SHIFT,
> +	HCLK_TOP_SEL_150M		= 0,
> +	HCLK_TOP_SEL_100M,
> +	HCLK_TOP_SEL_75M,
> +	HCLK_TOP_SEL_24M,
> +	ACLK_TOP_LOW_SEL_SHIFT		= 4,
> +	ACLK_TOP_LOW_SEL_MASK		= 3 << ACLK_TOP_LOW_SEL_SHIFT,
> +	ACLK_TOP_LOW_SEL_400M		= 0,
> +	ACLK_TOP_LOW_SEL_300M,
> +	ACLK_TOP_LOW_SEL_200M,
> +	ACLK_TOP_LOW_SEL_24M,
> +	ACLK_TOP_HIGH_SEL_SHIFT		= 0,
> +	ACLK_TOP_HIGH_SEL_MASK		= 3 << ACLK_TOP_HIGH_SEL_SHIFT,
> +	ACLK_TOP_HIGH_SEL_500M		= 0,
> +	ACLK_TOP_HIGH_SEL_400M,
> +	ACLK_TOP_HIGH_SEL_300M,
> +	ACLK_TOP_HIGH_SEL_24M,
> +
> +	/* CRU_CLK_SEL78_CON */
> +	CPLL_500M_DIV_SHIFT		= 8,
> +	CPLL_500M_DIV_MASK		= 0x1f << CPLL_500M_DIV_SHIFT,
> +
> +	/* CRU_CLK_SEL79_CON */
> +	CPLL_250M_DIV_SHIFT		= 8,
> +	CPLL_250M_DIV_MASK		= 0x1f << CPLL_250M_DIV_SHIFT,
> +	CPLL_333M_DIV_SHIFT		= 0,
> +	CPLL_333M_DIV_MASK		= 0x1f << CPLL_333M_DIV_SHIFT,
> +
> +	/* CRU_CLK_SEL80_CON */
> +	CPLL_62P5M_DIV_SHIFT		= 8,
> +	CPLL_62P5M_DIV_MASK		= 0x1f << CPLL_62P5M_DIV_SHIFT,
> +	CPLL_125M_DIV_SHIFT		= 0,
> +	CPLL_125M_DIV_MASK		= 0x1f << CPLL_125M_DIV_SHIFT,
> +
> +	/* CRU_CLK_SEL81_CON */
> +	CPLL_25M_DIV_SHIFT		= 8,
> +	CPLL_25M_DIV_MASK		= 0x1f << CPLL_25M_DIV_SHIFT,
> +	CPLL_50M_DIV_SHIFT		= 0,
> +	CPLL_50M_DIV_MASK		= 0x1f << CPLL_50M_DIV_SHIFT,
> +
> +	/* CRU_CLK_SEL82_CON */
> +	CPLL_100M_DIV_SHIFT		= 0,
> +	CPLL_100M_DIV_MASK		= 0x1f << CPLL_100M_DIV_SHIFT,
> +};
> +#endif
> diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
> index 4cfcf8330929..913f611a0ff8 100644
> --- a/drivers/clk/rockchip/Makefile
> +++ b/drivers/clk/rockchip/Makefile
> @@ -14,4 +14,5 @@ obj-$(CONFIG_ROCKCHIP_RK3308) += clk_rk3308.o
>   obj-$(CONFIG_ROCKCHIP_RK3328) += clk_rk3328.o
>   obj-$(CONFIG_ROCKCHIP_RK3368) += clk_rk3368.o
>   obj-$(CONFIG_ROCKCHIP_RK3399) += clk_rk3399.o
> +obj-$(CONFIG_ROCKCHIP_RK3568) += clk_rk3568.o
>   obj-$(CONFIG_ROCKCHIP_RV1108) += clk_rv1108.o
> diff --git a/drivers/clk/rockchip/clk_rk3568.c b/drivers/clk/rockchip/clk_rk3568.c
> new file mode 100644
> index 000000000000..359aca358e0d
> --- /dev/null
> +++ b/drivers/clk/rockchip/clk_rk3568.c
> @@ -0,0 +1,2908 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2021 Fuzhou Rockchip Electronics Co., Ltd
Please remove "Fuzhou".
> + * Author: Elaine Zhang <zhangqing@rock-chips.com>
> + */
> +
> +#include <common.h>
> +#include <bitfield.h>
> +#include <clk-uclass.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <syscon.h>
> +#include <asm/arch-rockchip/cru_rk3568.h>
> +#include <asm/arch-rockchip/clock.h>
> +#include <asm/arch-rockchip/hardware.h>
> +#include <asm/io.h>
> +#include <dm/lists.h>
> +#include <dt-bindings/clock/rk3568-cru.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#if CONFIG_IS_ENABLED(OF_PLATDATA)
> +struct rk3568_clk_plat {
> +	struct dtd_rockchip_rk3568_cru dtd;
> +};
> +
> +struct rk3568_pmuclk_plat {
> +	struct dtd_rockchip_rk3568_pmucru dtd;
> +};
> +#endif
> +
> +#define RK3568_CPUCLK_RATE(_rate, _aclk_div, _pclk_div)		\
> +{								\
> +	.rate	= _rate##U,					\
> +	.aclk_div = _aclk_div,					\
> +	.pclk_div = _pclk_div,					\
> +}
> +
> +#define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
> +
> +static struct rockchip_cpu_rate_table rk3568_cpu_rates[] = {
> +	RK3568_CPUCLK_RATE(1416000000, 1, 5),
> +	RK3568_CPUCLK_RATE(1296000000, 1, 5),
> +	RK3568_CPUCLK_RATE(1200000000, 1, 3),
> +	RK3568_CPUCLK_RATE(1104000000, 1, 3),
> +	RK3568_CPUCLK_RATE(1008000000, 1, 3),
> +	RK3568_CPUCLK_RATE(912000000, 1, 3),
> +	RK3568_CPUCLK_RATE(816000000, 1, 3),
> +	RK3568_CPUCLK_RATE(600000000, 1, 1),
> +	RK3568_CPUCLK_RATE(408000000, 1, 1),
> +	{ /* sentinel */ },
> +};
> +
> +static struct rockchip_pll_rate_table rk3568_pll_rates[] = {
> +	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
> +	RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
> +	RK3036_PLL_RATE(1416000000, 1, 118, 2, 1, 1, 0),
> +	RK3036_PLL_RATE(1296000000, 1, 108, 2, 1, 1, 0),
> +	RK3036_PLL_RATE(1200000000, 1, 100, 2, 1, 1, 0),
> +	RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0),
> +	RK3036_PLL_RATE(1104000000, 1, 92, 2, 1, 1, 0),
> +	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
> +	RK3036_PLL_RATE(1000000000, 3, 250, 2, 1, 1, 0),
> +	RK3036_PLL_RATE(912000000, 1, 76, 2, 1, 1, 0),
> +	RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
> +	RK3036_PLL_RATE(600000000, 1, 100, 4, 1, 1, 0),
> +	RK3036_PLL_RATE(594000000, 1, 99, 4, 1, 1, 0),
> +	RK3036_PLL_RATE(500000000, 1, 125, 6, 1, 1, 0),
> +	RK3036_PLL_RATE(408000000, 1, 68, 2, 2, 1, 0),
> +	RK3036_PLL_RATE(400000000, 1, 100, 6, 1, 1, 0),
> +	RK3036_PLL_RATE(200000000, 1, 100, 6, 2, 1, 0),
> +	RK3036_PLL_RATE(100000000, 1, 150, 6, 6, 1, 0),
> +	{ /* sentinel */ },
> +};
> +
> +static struct rockchip_pll_clock rk3568_pll_clks[] = {
> +	[APLL] = PLL(pll_rk3328, PLL_APLL, RK3568_PLL_CON(0),
> +		     RK3568_MODE_CON, 0, 10, 0, rk3568_pll_rates),
> +	[DPLL] = PLL(pll_rk3328, PLL_DPLL, RK3568_PLL_CON(8),
> +		     RK3568_MODE_CON, 2, 10, 0, NULL),
> +	[CPLL] = PLL(pll_rk3328, PLL_CPLL, RK3568_PLL_CON(24),
> +		     RK3568_MODE_CON, 4, 10, 0, rk3568_pll_rates),
> +	[GPLL] = PLL(pll_rk3328, PLL_HPLL, RK3568_PLL_CON(16),
> +		     RK3568_MODE_CON, 6, 10, 0, rk3568_pll_rates),
> +	[NPLL] = PLL(pll_rk3328, PLL_NPLL, RK3568_PLL_CON(32),
> +		     RK3568_MODE_CON, 10, 10, 0, rk3568_pll_rates),
> +	[VPLL] = PLL(pll_rk3328, PLL_VPLL, RK3568_PLL_CON(40),
> +		     RK3568_MODE_CON, 12, 10, 0, rk3568_pll_rates),
> +	[PPLL] = PLL(pll_rk3328, PLL_PPLL, RK3568_PMU_PLL_CON(0),
> +		     RK3568_PMU_MODE, 0, 10, 0, rk3568_pll_rates),
> +	[HPLL] = PLL(pll_rk3328, PLL_HPLL, RK3568_PMU_PLL_CON(16),
> +		     RK3568_PMU_MODE, 2, 10, 0, rk3568_pll_rates),
> +};
> +
> +static ulong __maybe_unused
> +rk3568_pmu_pll_set_rate(struct rk3568_clk_priv *priv,
> +			ulong pll_id, ulong rate)
> +{
> +	struct udevice *pmucru_dev;
> +	struct rk3568_pmuclk_priv *pmu_priv;
> +	int ret;
> +
> +	ret = uclass_get_device_by_driver(UCLASS_CLK,
> +					  DM_DRIVER_GET(rockchip_rk3568_pmucru),
> +					  &pmucru_dev);
> +	if (ret) {
> +		printf("%s: could not find pmucru device\n", __func__);
> +		return ret;
> +	}
> +	pmu_priv = dev_get_priv(pmucru_dev);
> +
> +	rockchip_pll_set_rate(&rk3568_pll_clks[pll_id],
> +			      pmu_priv->pmucru, pll_id, rate);
> +
> +	return 0;
> +}
> +
> +static ulong rk3568_pmu_pll_get_rate(struct rk3568_clk_priv *priv,
> +				     ulong pll_id)
> +{
> +	struct udevice *pmucru_dev;
> +	struct rk3568_pmuclk_priv *pmu_priv;
> +	int ret;
> +
> +	ret = uclass_get_device_by_driver(UCLASS_CLK,
> +					  DM_DRIVER_GET(rockchip_rk3568_pmucru),
> +					  &pmucru_dev);
> +	if (ret) {
> +		printf("%s: could not find pmucru device\n", __func__);
> +		return ret;
> +	}
> +	pmu_priv = dev_get_priv(pmucru_dev);
> +
> +	return rockchip_pll_get_rate(&rk3568_pll_clks[pll_id],
> +				      pmu_priv->pmucru, pll_id);
> +}
> +
> +/*
> + *
> + * rational_best_approximation(31415, 10000,
> + *		(1 << 8) - 1, (1 << 5) - 1, &n, &d);
> + *
> + * you may look at given_numerator as a fixed point number,
> + * with the fractional part size described in given_denominator.
> + *
> + * for theoretical background, see:
> + * http://en.wikipedia.org/wiki/Continued_fraction
> + */
> +static void rational_best_approximation(unsigned long given_numerator,
> +					unsigned long given_denominator,
> +					unsigned long max_numerator,
> +					unsigned long max_denominator,
> +					unsigned long *best_numerator,
> +					unsigned long *best_denominator)
> +{
> +	unsigned long n, d, n0, d0, n1, d1;
> +
> +	n = given_numerator;
> +	d = given_denominator;
> +	n0 = 0;
> +	d1 = 0;
> +	n1 = 1;
> +	d0 = 1;
> +	for (;;) {
> +		unsigned long t, a;
> +
> +		if (n1 > max_numerator || d1 > max_denominator) {
> +			n1 = n0;
> +			d1 = d0;
> +			break;
> +		}
> +		if (d == 0)
> +			break;
> +		t = d;
> +		a = n / d;
> +		d = n % d;
> +		n = t;
> +		t = n0 + a * n1;
> +		n0 = n1;
> +		n1 = t;
> +		t = d0 + a * d1;
> +		d0 = d1;
> +		d1 = t;
> +	}
> +	*best_numerator = n1;
> +	*best_denominator = d1;
> +}
> +
> +static ulong rk3568_rtc32k_get_pmuclk(struct rk3568_pmuclk_priv *priv)
> +{
> +	struct rk3568_pmucru *pmucru = priv->pmucru;
> +	unsigned long m, n;
> +	u32 fracdiv;
> +
> +	fracdiv = readl(&pmucru->pmu_clksel_con[1]);
> +	m = fracdiv & RTC32K_FRAC_NUMERATOR_MASK;
> +	m >>= RTC32K_FRAC_NUMERATOR_SHIFT;
> +	n = fracdiv & RTC32K_FRAC_DENOMINATOR_MASK;
> +	n >>= RTC32K_FRAC_DENOMINATOR_SHIFT;
> +
> +	return OSC_HZ * m / n;
> +}
> +
> +static ulong rk3568_rtc32k_set_pmuclk(struct rk3568_pmuclk_priv *priv,
> +				      ulong rate)
> +{
> +	struct rk3568_pmucru *pmucru = priv->pmucru;
> +	unsigned long m, n, val;
> +
> +	rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK,
> +		     RTC32K_SEL_OSC0_DIV32K << RTC32K_SEL_SHIFT);
> +
> +	rational_best_approximation(rate, OSC_HZ,
> +				    GENMASK(16 - 1, 0),
> +				    GENMASK(16 - 1, 0),
> +				    &m, &n);
> +	val = m << RTC32K_FRAC_NUMERATOR_SHIFT | n;
> +	writel(val, &pmucru->pmu_clksel_con[1]);
> +
> +	return rk3568_rtc32k_get_pmuclk(priv);
> +}
> +
> +static ulong rk3568_i2c_get_pmuclk(struct rk3568_pmuclk_priv *priv,
> +				   ulong clk_id)
> +{
> +	struct rk3568_pmucru *pmucru = priv->pmucru;
> +	u32 div, con;
> +
> +	switch (clk_id) {
> +	case CLK_I2C0:
> +		con = readl(&pmucru->pmu_clksel_con[3]);
> +		div = (con & CLK_I2C0_DIV_MASK) >> CLK_I2C0_DIV_SHIFT;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return DIV_TO_RATE(priv->ppll_hz, div);
> +}
> +
> +static ulong rk3568_i2c_set_pmuclk(struct rk3568_pmuclk_priv *priv,
> +				   ulong clk_id, ulong rate)
> +{
> +	struct rk3568_pmucru *pmucru = priv->pmucru;
> +	int src_clk_div;
> +
> +	src_clk_div = DIV_ROUND_UP(priv->ppll_hz, rate);
> +	assert(src_clk_div - 1 <= 127);
> +
> +	switch (clk_id) {
> +	case CLK_I2C0:
> +		rk_clrsetreg(&pmucru->pmu_clksel_con[3], CLK_I2C0_DIV_MASK,
> +			     (src_clk_div - 1) << CLK_I2C0_DIV_SHIFT);
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return rk3568_i2c_get_pmuclk(priv, clk_id);
> +}
> +
> +static ulong rk3568_pwm_get_pmuclk(struct rk3568_pmuclk_priv *priv,
> +				   ulong clk_id)
> +{
> +	struct rk3568_pmucru *pmucru = priv->pmucru;
> +	u32 div, sel, con, parent;
> +
> +	switch (clk_id) {
> +	case CLK_PWM0:
> +		con = readl(&pmucru->pmu_clksel_con[6]);
> +		sel = (con & CLK_PWM0_SEL_MASK) >> CLK_PWM0_SEL_SHIFT;
> +		div = (con & CLK_PWM0_DIV_MASK) >> CLK_PWM0_DIV_SHIFT;
> +		if (sel == CLK_PWM0_SEL_XIN24M)
> +			parent = OSC_HZ;
> +		else
> +			parent = priv->ppll_hz;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return DIV_TO_RATE(parent, div);
> +}
> +
> +static ulong rk3568_pwm_set_pmuclk(struct rk3568_pmuclk_priv *priv,
> +				   ulong clk_id, ulong rate)
> +{
> +	struct rk3568_pmucru *pmucru = priv->pmucru;
> +	int src_clk_div;
> +
> +	switch (clk_id) {
> +	case CLK_PWM0:
> +		if (rate == OSC_HZ) {
> +			rk_clrsetreg(&pmucru->pmu_clksel_con[6],
> +				     CLK_PWM0_SEL_MASK | CLK_PWM0_DIV_MASK,
> +				     (CLK_PWM0_SEL_XIN24M <<
> +				      CLK_PWM0_SEL_SHIFT) |
> +				     0 << CLK_PWM0_SEL_SHIFT);
> +		} else {
> +			src_clk_div = DIV_ROUND_UP(priv->ppll_hz, rate);
> +			assert(src_clk_div - 1 <= 127);
> +			rk_clrsetreg(&pmucru->pmu_clksel_con[6],
> +				     CLK_PWM0_DIV_MASK | CLK_PWM0_DIV_MASK,
> +				     (CLK_PWM0_SEL_PPLL << CLK_PWM0_SEL_SHIFT) |
> +				     (src_clk_div - 1) << CLK_PWM0_DIV_SHIFT);
> +		}
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return rk3568_pwm_get_pmuclk(priv, clk_id);
> +}
> +
> +static ulong rk3568_pmu_get_pmuclk(struct rk3568_pmuclk_priv *priv)
> +{
> +	struct rk3568_pmucru *pmucru = priv->pmucru;
> +	u32 div, con, sel, parent;
> +
> +	con = readl(&pmucru->pmu_clksel_con[2]);
> +	sel = (con & PCLK_PDPMU_SEL_MASK) >> PCLK_PDPMU_SEL_SHIFT;
> +	div = (con & PCLK_PDPMU_DIV_MASK) >> PCLK_PDPMU_DIV_SHIFT;
> +	if (sel)
> +		parent = GPLL_HZ;
> +	else
> +		parent = priv->ppll_hz;
> +
> +	return DIV_TO_RATE(parent, div);
> +}
> +
> +static ulong rk3568_pmu_set_pmuclk(struct rk3568_pmuclk_priv *priv,
> +				   ulong rate)
> +{
> +	struct rk3568_pmucru *pmucru = priv->pmucru;
> +	int src_clk_div;
> +
> +	src_clk_div = DIV_ROUND_UP(priv->ppll_hz, rate);
> +	assert(src_clk_div - 1 <= 31);
> +
> +	rk_clrsetreg(&pmucru->pmu_clksel_con[2],
> +		     PCLK_PDPMU_DIV_MASK | PCLK_PDPMU_SEL_MASK,
> +		     (PCLK_PDPMU_SEL_PPLL << PCLK_PDPMU_SEL_SHIFT) |
> +		     ((src_clk_div - 1) << PCLK_PDPMU_DIV_SHIFT));
> +
> +	return rk3568_pmu_get_pmuclk(priv);
> +}
> +
> +static ulong rk3568_pmuclk_get_rate(struct clk *clk)
> +{
> +	struct rk3568_pmuclk_priv *priv = dev_get_priv(clk->dev);
> +	ulong rate = 0;
> +
> +	if (!priv->ppll_hz) {
> +		printf("%s ppll=%lu\n", __func__, priv->ppll_hz);
> +		return -ENOENT;
> +	}
> +
> +	debug("%s %ld\n", __func__, clk->id);
> +	switch (clk->id) {
> +	case PLL_PPLL:
> +		rate = rockchip_pll_get_rate(&rk3568_pll_clks[PPLL],
> +					     priv->pmucru, PPLL);
> +		break;
> +	case PLL_HPLL:
> +		rate = rockchip_pll_get_rate(&rk3568_pll_clks[HPLL],
> +					     priv->pmucru, HPLL);
> +		break;
> +	case CLK_RTC_32K:
> +	case CLK_RTC32K_FRAC:
> +		rate = rk3568_rtc32k_get_pmuclk(priv);
> +		break;
> +	case CLK_I2C0:
> +		rate = rk3568_i2c_get_pmuclk(priv, clk->id);
> +		break;
> +	case CLK_PWM0:
> +		rate = rk3568_pwm_get_pmuclk(priv, clk->id);
> +		break;
> +	case PCLK_PMU:
> +		rate = rk3568_pmu_get_pmuclk(priv);
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return rate;
> +}
> +
> +static ulong rk3568_pmuclk_set_rate(struct clk *clk, ulong rate)
> +{
> +	struct rk3568_pmuclk_priv *priv = dev_get_priv(clk->dev);
> +	ulong ret = 0;
> +
> +	if (!priv->ppll_hz) {
> +		printf("%s ppll=%lu\n", __func__, priv->ppll_hz);
> +		return -ENOENT;
> +	}
> +
> +	debug("%s %ld %ld\n", __func__, clk->id, rate);
> +	switch (clk->id) {
> +	case PLL_PPLL:
> +		ret = rockchip_pll_set_rate(&rk3568_pll_clks[PPLL],
> +					    priv->pmucru, PPLL, rate);
> +		priv->ppll_hz = rockchip_pll_get_rate(&rk3568_pll_clks[PPLL],
> +						      priv->pmucru, PPLL);
> +		break;
> +	case PLL_HPLL:
> +		ret = rockchip_pll_set_rate(&rk3568_pll_clks[HPLL],
> +					    priv->pmucru, HPLL, rate);
> +		priv->hpll_hz = rockchip_pll_get_rate(&rk3568_pll_clks[HPLL],
> +						      priv->pmucru, HPLL);
> +		break;
> +	case CLK_RTC_32K:
> +	case CLK_RTC32K_FRAC:
> +		ret = rk3568_rtc32k_set_pmuclk(priv, rate);
> +		break;
> +	case CLK_I2C0:
> +		ret = rk3568_i2c_set_pmuclk(priv, clk->id, rate);
> +		break;
> +	case CLK_PWM0:
> +		ret = rk3568_pwm_set_pmuclk(priv, clk->id, rate);
> +		break;
> +	case PCLK_PMU:
> +		ret = rk3568_pmu_set_pmuclk(priv, rate);
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return ret;
> +}
> +
> +static int rk3568_rtc32k_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	struct rk3568_pmuclk_priv *priv = dev_get_priv(clk->dev);
> +	struct rk3568_pmucru *pmucru = priv->pmucru;
> +
> +	if (parent->id == CLK_RTC32K_FRAC)
> +		rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK,
> +			     RTC32K_SEL_OSC0_DIV32K << RTC32K_SEL_SHIFT);
> +	else
> +		rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK,
> +			     RTC32K_SEL_OSC1_32K << RTC32K_SEL_SHIFT);
> +
> +	return 0;
> +}
> +
> +static int rk3568_pmuclk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	switch (clk->id) {
> +	case CLK_RTC_32K:
> +		return rk3568_rtc32k_set_parent(clk, parent);
> +	default:
> +		return -ENOENT;
> +	}
> +}
> +
> +static struct clk_ops rk3568_pmuclk_ops = {
> +	.get_rate = rk3568_pmuclk_get_rate,
> +	.set_rate = rk3568_pmuclk_set_rate,
> +	.set_parent = rk3568_pmuclk_set_parent,
> +};
> +
> +static int rk3568_pmuclk_probe(struct udevice *dev)
> +{
> +	struct rk3568_pmuclk_priv *priv = dev_get_priv(dev);
> +	int ret = 0;
> +
> +	if (priv->ppll_hz != PPLL_HZ) {
> +		ret = rockchip_pll_set_rate(&rk3568_pll_clks[PPLL],
> +					    priv->pmucru,
> +					    PPLL, PPLL_HZ);
> +		if (!ret)
> +			priv->ppll_hz = PPLL_HZ;
> +	}
> +
> +	/* Ungate PCIe30phy refclk_m and refclk_n */
> +	rk_clrsetreg(&priv->pmucru->pmu_clkgate_con[2], 0x3 << 13, 0 << 13);
> +	return 0;
> +}
> +
> +static int rk3568_pmuclk_ofdata_to_platdata(struct udevice *dev)
> +{
> +	struct rk3568_pmuclk_priv *priv = dev_get_priv(dev);
> +
> +	priv->pmucru = dev_read_addr_ptr(dev);
> +
> +	return 0;
> +}
> +
> +static int rk3568_pmuclk_bind(struct udevice *dev)
> +{
> +#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
> +	int ret = 0;
> +
> +	ret = offsetof(struct rk3568_pmucru, pmu_softrst_con[0]);
> +	ret = rockchip_reset_bind(dev, ret, 1);
> +	if (ret)
> +		debug("Warning: pmucru software reset driver bind faile\n");
> +#endif
> +
> +	return 0;
> +}
> +
> +static const struct udevice_id rk3568_pmuclk_ids[] = {
> +	{ .compatible = "rockchip,rk3568-pmucru" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(rockchip_rk3568_pmucru) = {
> +	.name		= "rockchip_rk3568_pmucru",
> +	.id		= UCLASS_CLK,
> +	.of_match	= rk3568_pmuclk_ids,
> +	.priv_auto = sizeof(struct rk3568_pmuclk_priv),
> +	.of_to_plat = rk3568_pmuclk_ofdata_to_platdata,
> +	.ops		= &rk3568_pmuclk_ops,
> +	.bind		= rk3568_pmuclk_bind,
> +	.probe		= rk3568_pmuclk_probe,
> +#if CONFIG_IS_ENABLED(OF_PLATDATA)
> +	.plat_auto	= sizeof(struct rk3568_pmuclk_plat),
> +#endif
> +
> +};
> +
> +static int rk3568_armclk_set_clk(struct rk3568_clk_priv *priv, ulong hz)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	const struct rockchip_cpu_rate_table *rate;
> +	ulong old_rate;
> +
> +	rate = rockchip_get_cpu_settings(rk3568_cpu_rates, hz);
> +	if (!rate) {
> +		printf("%s unsupported rate\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	rk_clrsetreg(&cru->clksel_con[0],
> +		     CLK_CORE_PRE_SEL_MASK,
> +		     (CLK_CORE_PRE_SEL_SRC << CLK_CORE_PRE_SEL_SHIFT));
> +	rk_clrsetreg(&cru->clksel_con[2],
> +		     SCLK_CORE_PRE_SEL_MASK |
> +		     SCLK_CORE_SRC_SEL_MASK |
> +		     SCLK_CORE_SRC_DIV_MASK,
> +		     (SCLK_CORE_PRE_SEL_SRC <<
> +		      SCLK_CORE_PRE_SEL_SHIFT) |
> +		     (SCLK_CORE_SRC_SEL_APLL <<
> +		      SCLK_CORE_SRC_SEL_SHIFT) |
> +		     (1 << SCLK_CORE_SRC_DIV_SHIFT));
> +
> +	/*
> +	 * set up dependent divisors for DBG and ACLK clocks.
> +	 */
> +	old_rate = rockchip_pll_get_rate(&rk3568_pll_clks[APLL],
> +					 priv->cru, APLL);
> +	if (old_rate > hz) {
> +		if (rockchip_pll_set_rate(&rk3568_pll_clks[APLL],
> +					  priv->cru, APLL, hz))
> +			return -EINVAL;
> +		rk_clrsetreg(&cru->clksel_con[3],
> +			     GICCLK_CORE_DIV_MASK | ATCLK_CORE_DIV_MASK,
> +			     rate->pclk_div << GICCLK_CORE_DIV_SHIFT |
> +			     rate->pclk_div << ATCLK_CORE_DIV_SHIFT);
> +		rk_clrsetreg(&cru->clksel_con[4],
> +			     PERIPHCLK_CORE_PRE_DIV_MASK |
> +			     PCLK_CORE_PRE_DIV_MASK,
> +			     rate->pclk_div << PCLK_CORE_PRE_DIV_SHIFT |
> +			     rate->pclk_div << PERIPHCLK_CORE_PRE_DIV_SHIFT);
> +		rk_clrsetreg(&cru->clksel_con[5],
> +			     ACLK_CORE_NDFT_DIV_MASK,
> +			     rate->aclk_div << ACLK_CORE_NDFT_DIV_SHIFT);
> +	} else if (old_rate < hz) {
> +		rk_clrsetreg(&cru->clksel_con[3],
> +			     GICCLK_CORE_DIV_MASK | ATCLK_CORE_DIV_MASK,
> +			     rate->pclk_div << GICCLK_CORE_DIV_SHIFT |
> +			     rate->pclk_div << ATCLK_CORE_DIV_SHIFT);
> +		rk_clrsetreg(&cru->clksel_con[4],
> +			     PERIPHCLK_CORE_PRE_DIV_MASK |
> +			     PCLK_CORE_PRE_DIV_MASK,
> +			     rate->pclk_div << PCLK_CORE_PRE_DIV_SHIFT |
> +			     rate->pclk_div << PERIPHCLK_CORE_PRE_DIV_SHIFT);
> +		rk_clrsetreg(&cru->clksel_con[5],
> +			     ACLK_CORE_NDFT_DIV_MASK,
> +			     rate->aclk_div << ACLK_CORE_NDFT_DIV_SHIFT);
> +		if (rockchip_pll_set_rate(&rk3568_pll_clks[APLL],
> +					  priv->cru, APLL, hz))
> +			return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static ulong rk3568_cpll_div_get_rate(struct rk3568_clk_priv *priv,
> +				      ulong clk_id)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int div, mask, shift, con;
> +
> +	switch (clk_id) {
> +	case CPLL_500M:
> +		con = 78;
> +		mask = CPLL_500M_DIV_MASK;
> +		shift = CPLL_500M_DIV_SHIFT;
> +		break;
> +	case CPLL_333M:
> +		con = 79;
> +		mask = CPLL_333M_DIV_MASK;
> +		shift = CPLL_333M_DIV_SHIFT;
> +		break;
> +	case CPLL_250M:
> +		con = 79;
> +		mask = CPLL_250M_DIV_MASK;
> +		shift = CPLL_250M_DIV_SHIFT;
> +		break;
> +	case CPLL_125M:
> +		con = 80;
> +		mask = CPLL_125M_DIV_MASK;
> +		shift = CPLL_125M_DIV_SHIFT;
> +		break;
> +	case CPLL_100M:
> +		con = 82;
> +		mask = CPLL_100M_DIV_MASK;
> +		shift = CPLL_100M_DIV_SHIFT;
> +		break;
> +	case CPLL_62P5M:
> +		con = 80;
> +		mask = CPLL_62P5M_DIV_MASK;
> +		shift = CPLL_62P5M_DIV_SHIFT;
> +		break;
> +	case CPLL_50M:
> +		con = 81;
> +		mask = CPLL_50M_DIV_MASK;
> +		shift = CPLL_50M_DIV_SHIFT;
> +		break;
> +	case CPLL_25M:
> +		con = 81;
> +		mask = CPLL_25M_DIV_MASK;
> +		shift = CPLL_25M_DIV_SHIFT;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	div = (readl(&cru->clksel_con[con]) & mask) >> shift;
> +	return DIV_TO_RATE(priv->cpll_hz, div);
> +}
> +
> +static ulong rk3568_cpll_div_set_rate(struct rk3568_clk_priv *priv,
> +				      ulong clk_id, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int div, mask, shift, con;
> +
> +	switch (clk_id) {
> +	case CPLL_500M:
> +		con = 78;
> +		mask = CPLL_500M_DIV_MASK;
> +		shift = CPLL_500M_DIV_SHIFT;
> +		break;
> +	case CPLL_333M:
> +		con = 79;
> +		mask = CPLL_333M_DIV_MASK;
> +		shift = CPLL_333M_DIV_SHIFT;
> +		break;
> +	case CPLL_250M:
> +		con = 79;
> +		mask = CPLL_250M_DIV_MASK;
> +		shift = CPLL_250M_DIV_SHIFT;
> +		break;
> +	case CPLL_125M:
> +		con = 80;
> +		mask = CPLL_125M_DIV_MASK;
> +		shift = CPLL_125M_DIV_SHIFT;
> +		break;
> +	case CPLL_100M:
> +		con = 82;
> +		mask = CPLL_100M_DIV_MASK;
> +		shift = CPLL_100M_DIV_SHIFT;
> +		break;
> +	case CPLL_62P5M:
> +		con = 80;
> +		mask = CPLL_62P5M_DIV_MASK;
> +		shift = CPLL_62P5M_DIV_SHIFT;
> +		break;
> +	case CPLL_50M:
> +		con = 81;
> +		mask = CPLL_50M_DIV_MASK;
> +		shift = CPLL_50M_DIV_SHIFT;
> +		break;
> +	case CPLL_25M:
> +		con = 81;
> +		mask = CPLL_25M_DIV_MASK;
> +		shift = CPLL_25M_DIV_SHIFT;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	div = DIV_ROUND_UP(priv->cpll_hz, rate);
> +	assert(div - 1 <= 31);
> +	rk_clrsetreg(&cru->clksel_con[con],
> +		     mask, (div - 1) << shift);
> +	return rk3568_cpll_div_get_rate(priv, clk_id);
> +}
> +
> +static ulong rk3568_bus_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 con, sel, rate;
> +
> +	switch (clk_id) {
> +	case ACLK_BUS:
> +		con = readl(&cru->clksel_con[50]);
> +		sel = (con & ACLK_BUS_SEL_MASK) >> ACLK_BUS_SEL_SHIFT;
> +		if (sel == ACLK_BUS_SEL_200M)
> +			rate = 200 * MHz;
> +		else if (sel == ACLK_BUS_SEL_150M)
> +			rate = 150 * MHz;
> +		else if (sel == ACLK_BUS_SEL_100M)
> +			rate = 100 * MHz;
> +		else
> +			rate = OSC_HZ;
> +		break;
> +	case PCLK_BUS:
> +	case PCLK_WDT_NS:
> +		con = readl(&cru->clksel_con[50]);
> +		sel = (con & PCLK_BUS_SEL_MASK) >> PCLK_BUS_SEL_SHIFT;
> +		if (sel == PCLK_BUS_SEL_100M)
> +			rate = 100 * MHz;
> +		else if (sel == PCLK_BUS_SEL_75M)
> +			rate = 75 * MHz;
> +		else if (sel == PCLK_BUS_SEL_50M)
> +			rate = 50 * MHz;
> +		else
> +			rate = OSC_HZ;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return rate;
> +}
> +
> +static ulong rk3568_bus_set_clk(struct rk3568_clk_priv *priv,
> +				ulong clk_id, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int src_clk;
> +
> +	switch (clk_id) {
> +	case ACLK_BUS:
> +		if (rate == 200 * MHz)
> +			src_clk = ACLK_BUS_SEL_200M;
> +		else if (rate == 150 * MHz)
> +			src_clk = ACLK_BUS_SEL_150M;
> +		else if (rate == 100 * MHz)
> +			src_clk = ACLK_BUS_SEL_100M;
> +		else
> +			src_clk = ACLK_BUS_SEL_24M;
> +		rk_clrsetreg(&cru->clksel_con[50],
> +			     ACLK_BUS_SEL_MASK,
> +			     src_clk << ACLK_BUS_SEL_SHIFT);
> +		break;
> +	case PCLK_BUS:
> +	case PCLK_WDT_NS:
> +		if (rate == 100 * MHz)
> +			src_clk = PCLK_BUS_SEL_100M;
> +		else if (rate == 75 * MHz)
> +			src_clk = PCLK_BUS_SEL_75M;
> +		else if (rate == 50 * MHz)
> +			src_clk = PCLK_BUS_SEL_50M;
> +		else
> +			src_clk = PCLK_BUS_SEL_24M;
> +		rk_clrsetreg(&cru->clksel_con[50],
> +			     PCLK_BUS_SEL_MASK,
> +			     src_clk << PCLK_BUS_SEL_SHIFT);
> +		break;
> +
> +	default:
> +		printf("do not support this bus freq\n");
> +		return -EINVAL;
> +	}
> +
> +	return rk3568_bus_get_clk(priv, clk_id);
> +}
> +
> +static ulong rk3568_perimid_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 con, sel, rate;
> +
> +	switch (clk_id) {
> +	case ACLK_PERIMID:
> +		con = readl(&cru->clksel_con[10]);
> +		sel = (con & ACLK_PERIMID_SEL_MASK) >> ACLK_PERIMID_SEL_SHIFT;
> +		if (sel == ACLK_PERIMID_SEL_300M)
> +			rate = 300 * MHz;
> +		else if (sel == ACLK_PERIMID_SEL_200M)
> +			rate = 200 * MHz;
> +		else if (sel == ACLK_PERIMID_SEL_100M)
> +			rate = 100 * MHz;
> +		else
> +			rate = OSC_HZ;
> +		break;
> +	case HCLK_PERIMID:
> +		con = readl(&cru->clksel_con[10]);
> +		sel = (con & HCLK_PERIMID_SEL_MASK) >> HCLK_PERIMID_SEL_SHIFT;
> +		if (sel == HCLK_PERIMID_SEL_150M)
> +			rate = 150 * MHz;
> +		else if (sel == HCLK_PERIMID_SEL_100M)
> +			rate = 100 * MHz;
> +		else if (sel == HCLK_PERIMID_SEL_75M)
> +			rate = 75 * MHz;
> +		else
> +			rate = OSC_HZ;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return rate;
> +}
> +
> +static ulong rk3568_perimid_set_clk(struct rk3568_clk_priv *priv,
> +				    ulong clk_id, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int src_clk;
> +
> +	switch (clk_id) {
> +	case ACLK_PERIMID:
> +		if (rate == 300 * MHz)
> +			src_clk = ACLK_PERIMID_SEL_300M;
> +		else if (rate == 200 * MHz)
> +			src_clk = ACLK_PERIMID_SEL_200M;
> +		else if (rate == 100 * MHz)
> +			src_clk = ACLK_PERIMID_SEL_100M;
> +		else
> +			src_clk = ACLK_PERIMID_SEL_24M;
> +		rk_clrsetreg(&cru->clksel_con[10],
> +			     ACLK_PERIMID_SEL_MASK,
> +			     src_clk << ACLK_PERIMID_SEL_SHIFT);
> +		break;
> +	case HCLK_PERIMID:
> +		if (rate == 150 * MHz)
> +			src_clk = HCLK_PERIMID_SEL_150M;
> +		else if (rate == 100 * MHz)
> +			src_clk = HCLK_PERIMID_SEL_100M;
> +		else if (rate == 75 * MHz)
> +			src_clk = HCLK_PERIMID_SEL_75M;
> +		else
> +			src_clk = HCLK_PERIMID_SEL_24M;
> +		rk_clrsetreg(&cru->clksel_con[10],
> +			     HCLK_PERIMID_SEL_MASK,
> +			     src_clk << HCLK_PERIMID_SEL_SHIFT);
> +		break;
> +
> +	default:
> +		printf("do not support this permid freq\n");
> +		return -EINVAL;
> +	}
> +
> +	return rk3568_perimid_get_clk(priv, clk_id);
> +}
> +
> +static ulong rk3568_top_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 con, sel, rate;
> +
> +	switch (clk_id) {
> +	case ACLK_TOP_HIGH:
> +		con = readl(&cru->clksel_con[73]);
> +		sel = (con & ACLK_TOP_HIGH_SEL_MASK) >> ACLK_TOP_HIGH_SEL_SHIFT;
> +		if (sel == ACLK_TOP_HIGH_SEL_500M)
> +			rate = 500 * MHz;
> +		else if (sel == ACLK_TOP_HIGH_SEL_400M)
> +			rate = 400 * MHz;
> +		else if (sel == ACLK_TOP_HIGH_SEL_300M)
> +			rate = 300 * MHz;
> +		else
> +			rate = OSC_HZ;
> +		break;
> +	case ACLK_TOP_LOW:
> +		con = readl(&cru->clksel_con[73]);
> +		sel = (con & ACLK_TOP_LOW_SEL_MASK) >> ACLK_TOP_LOW_SEL_SHIFT;
> +		if (sel == ACLK_TOP_LOW_SEL_400M)
> +			rate = 400 * MHz;
> +		else if (sel == ACLK_TOP_LOW_SEL_300M)
> +			rate = 300 * MHz;
> +		else if (sel == ACLK_TOP_LOW_SEL_200M)
> +			rate = 200 * MHz;
> +		else
> +			rate = OSC_HZ;
> +		break;
> +	case HCLK_TOP:
> +		con = readl(&cru->clksel_con[73]);
> +		sel = (con & HCLK_TOP_SEL_MASK) >> HCLK_TOP_SEL_SHIFT;
> +		if (sel == HCLK_TOP_SEL_150M)
> +			rate = 150 * MHz;
> +		else if (sel == HCLK_TOP_SEL_100M)
> +			rate = 100 * MHz;
> +		else if (sel == HCLK_TOP_SEL_75M)
> +			rate = 75 * MHz;
> +		else
> +			rate = OSC_HZ;
> +		break;
> +	case PCLK_TOP:
> +		con = readl(&cru->clksel_con[73]);
> +		sel = (con & PCLK_TOP_SEL_MASK) >> PCLK_TOP_SEL_SHIFT;
> +		if (sel == PCLK_TOP_SEL_100M)
> +			rate = 100 * MHz;
> +		else if (sel == PCLK_TOP_SEL_75M)
> +			rate = 75 * MHz;
> +		else if (sel == PCLK_TOP_SEL_50M)
> +			rate = 50 * MHz;
> +		else
> +			rate = OSC_HZ;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return rate;
> +}
> +
> +static ulong rk3568_top_set_clk(struct rk3568_clk_priv *priv,
> +				ulong clk_id, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int src_clk;
> +
> +	switch (clk_id) {
> +	case ACLK_TOP_HIGH:
> +		if (rate == 500 * MHz)
> +			src_clk = ACLK_TOP_HIGH_SEL_500M;
> +		else if (rate == 400 * MHz)
> +			src_clk = ACLK_TOP_HIGH_SEL_400M;
> +		else if (rate == 300 * MHz)
> +			src_clk = ACLK_TOP_HIGH_SEL_300M;
> +		else
> +			src_clk = ACLK_TOP_HIGH_SEL_24M;
> +		rk_clrsetreg(&cru->clksel_con[73],
> +			     ACLK_TOP_HIGH_SEL_MASK,
> +			     src_clk << ACLK_TOP_HIGH_SEL_SHIFT);
> +		break;
> +	case ACLK_TOP_LOW:
> +		if (rate == 400 * MHz)
> +			src_clk = ACLK_TOP_LOW_SEL_400M;
> +		else if (rate == 300 * MHz)
> +			src_clk = ACLK_TOP_LOW_SEL_300M;
> +		else if (rate == 200 * MHz)
> +			src_clk = ACLK_TOP_LOW_SEL_200M;
> +		else
> +			src_clk = ACLK_TOP_LOW_SEL_24M;
> +		rk_clrsetreg(&cru->clksel_con[73],
> +			     ACLK_TOP_LOW_SEL_MASK,
> +			     src_clk << ACLK_TOP_LOW_SEL_SHIFT);
> +		break;
> +	case HCLK_TOP:
> +		if (rate == 150 * MHz)
> +			src_clk = HCLK_TOP_SEL_150M;
> +		else if (rate == 100 * MHz)
> +			src_clk = HCLK_TOP_SEL_100M;
> +		else if (rate == 75 * MHz)
> +			src_clk = HCLK_TOP_SEL_75M;
> +		else
> +			src_clk = HCLK_TOP_SEL_24M;
> +		rk_clrsetreg(&cru->clksel_con[73],
> +			     HCLK_TOP_SEL_MASK,
> +			     src_clk << HCLK_TOP_SEL_SHIFT);
> +		break;
> +	case PCLK_TOP:
> +		if (rate == 100 * MHz)
> +			src_clk = PCLK_TOP_SEL_100M;
> +		else if (rate == 75 * MHz)
> +			src_clk = PCLK_TOP_SEL_75M;
> +		else if (rate == 50 * MHz)
> +			src_clk = PCLK_TOP_SEL_50M;
> +		else
> +			src_clk = PCLK_TOP_SEL_24M;
> +		rk_clrsetreg(&cru->clksel_con[73],
> +			     PCLK_TOP_SEL_MASK,
> +			     src_clk << PCLK_TOP_SEL_SHIFT);
> +		break;
> +
> +	default:
> +		printf("do not support this permid freq\n");
> +		return -EINVAL;
> +	}
> +
> +	return rk3568_top_get_clk(priv, clk_id);
> +}
> +
> +static ulong rk3568_i2c_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 sel, con;
> +	ulong rate;
> +
> +	switch (clk_id) {
> +	case CLK_I2C1:
> +	case CLK_I2C2:
> +	case CLK_I2C3:
> +	case CLK_I2C4:
> +	case CLK_I2C5:
> +		con = readl(&cru->clksel_con[71]);
> +		sel = (con & CLK_I2C_SEL_MASK) >> CLK_I2C_SEL_SHIFT;
> +		if (sel == CLK_I2C_SEL_200M)
> +			rate = 200 * MHz;
> +		else if (sel == CLK_I2C_SEL_100M)
> +			rate = 100 * MHz;
> +		else if (sel == CLK_I2C_SEL_CPLL_100M)
> +			rate = 100 * MHz;
> +		else
> +			rate = OSC_HZ;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return rate;
> +}
> +
> +static ulong rk3568_i2c_set_clk(struct rk3568_clk_priv *priv, ulong clk_id,
> +				ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int src_clk;
> +
> +	if (rate == 200 * MHz)
> +		src_clk = CLK_I2C_SEL_200M;
> +	else if (rate == 100 * MHz)
> +		src_clk = CLK_I2C_SEL_100M;
> +	else
> +		src_clk = CLK_I2C_SEL_24M;
> +
> +	switch (clk_id) {
> +	case CLK_I2C1:
> +	case CLK_I2C2:
> +	case CLK_I2C3:
> +	case CLK_I2C4:
> +	case CLK_I2C5:
> +		rk_clrsetreg(&cru->clksel_con[71], CLK_I2C_SEL_MASK,
> +			     src_clk << CLK_I2C_SEL_SHIFT);
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return rk3568_i2c_get_clk(priv, clk_id);
> +}
> +
> +static ulong rk3568_spi_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 sel, con;
> +
> +	con = readl(&cru->clksel_con[72]);
> +
> +	switch (clk_id) {
> +	case CLK_SPI0:
> +		sel = (con & CLK_SPI0_SEL_MASK) >> CLK_SPI0_SEL_SHIFT;
> +		break;
> +	case CLK_SPI1:
> +		sel = (con & CLK_SPI1_SEL_MASK) >> CLK_SPI1_SEL_SHIFT;
> +		break;
> +	case CLK_SPI2:
> +		sel = (con & CLK_SPI2_SEL_MASK) >> CLK_SPI2_SEL_SHIFT;
> +		break;
> +	case CLK_SPI3:
> +		sel = (con & CLK_SPI3_SEL_MASK) >> CLK_SPI3_SEL_SHIFT;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	switch (sel) {
> +	case CLK_SPI_SEL_200M:
> +		return 200 * MHz;
> +	case CLK_SPI_SEL_24M:
> +		return OSC_HZ;
> +	case CLK_SPI_SEL_CPLL_100M:
> +		return 100 * MHz;
> +	default:
> +		return -ENOENT;
> +	}
> +}
> +
> +static ulong rk3568_spi_set_clk(struct rk3568_clk_priv *priv,
> +				ulong clk_id, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int src_clk;
> +
> +	if (rate == 200 * MHz)
> +		src_clk = CLK_SPI_SEL_200M;
> +	else if (rate == 100 * MHz)
> +		src_clk = CLK_SPI_SEL_CPLL_100M;
> +	else
> +		src_clk = CLK_SPI_SEL_24M;
> +
> +	switch (clk_id) {
> +	case CLK_SPI0:
> +		rk_clrsetreg(&cru->clksel_con[72],
> +			     CLK_SPI0_SEL_MASK,
> +			     src_clk << CLK_SPI0_SEL_SHIFT);
> +		break;
> +	case CLK_SPI1:
> +		rk_clrsetreg(&cru->clksel_con[72],
> +			     CLK_SPI1_SEL_MASK,
> +			     src_clk << CLK_SPI1_SEL_SHIFT);
> +		break;
> +	case CLK_SPI2:
> +		rk_clrsetreg(&cru->clksel_con[72],
> +			     CLK_SPI2_SEL_MASK,
> +			     src_clk << CLK_SPI2_SEL_SHIFT);
> +		break;
> +	case CLK_SPI3:
> +		rk_clrsetreg(&cru->clksel_con[72],
> +			     CLK_SPI3_SEL_MASK,
> +			     src_clk << CLK_SPI3_SEL_SHIFT);
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return rk3568_spi_get_clk(priv, clk_id);
> +}
> +
> +static ulong rk3568_pwm_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 sel, con;
> +
> +	con = readl(&cru->clksel_con[72]);
> +
> +	switch (clk_id) {
> +	case CLK_PWM1:
> +		sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM3_SEL_SHIFT;
> +		break;
> +	case CLK_PWM2:
> +		sel = (con & CLK_PWM2_SEL_MASK) >> CLK_PWM2_SEL_SHIFT;
> +		break;
> +	case CLK_PWM3:
> +		sel = (con & CLK_PWM3_SEL_MASK) >> CLK_PWM3_SEL_SHIFT;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	switch (sel) {
> +	case CLK_PWM_SEL_100M:
> +		return 100 * MHz;
> +	case CLK_PWM_SEL_24M:
> +		return OSC_HZ;
> +	case CLK_PWM_SEL_CPLL_100M:
> +		return 100 * MHz;
> +	default:
> +		return -ENOENT;
> +	}
> +}
> +
> +static ulong rk3568_pwm_set_clk(struct rk3568_clk_priv *priv,
> +				ulong clk_id, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int src_clk;
> +
> +	if (rate == 100 * MHz)
> +		src_clk = CLK_PWM_SEL_100M;
> +	else
> +		src_clk = CLK_PWM_SEL_24M;
> +
> +	switch (clk_id) {
> +	case CLK_PWM1:
> +		rk_clrsetreg(&cru->clksel_con[72],
> +			     CLK_PWM1_SEL_MASK,
> +			     src_clk << CLK_PWM1_SEL_SHIFT);
> +		break;
> +	case CLK_PWM2:
> +		rk_clrsetreg(&cru->clksel_con[72],
> +			     CLK_PWM2_SEL_MASK,
> +			     src_clk << CLK_PWM2_SEL_SHIFT);
> +		break;
> +	case CLK_PWM3:
> +		rk_clrsetreg(&cru->clksel_con[72],
> +			     CLK_PWM3_SEL_MASK,
> +			     src_clk << CLK_PWM3_SEL_SHIFT);
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return rk3568_pwm_get_clk(priv, clk_id);
> +}
> +
> +static ulong rk3568_adc_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 div, sel, con, prate;
> +
> +	switch (clk_id) {
> +	case CLK_SARADC:
> +		return OSC_HZ;
> +	case CLK_TSADC_TSEN:
> +		con = readl(&cru->clksel_con[51]);
> +		div = (con & CLK_TSADC_TSEN_DIV_MASK) >>
> +		      CLK_TSADC_TSEN_DIV_SHIFT;
> +		sel = (con & CLK_TSADC_TSEN_SEL_MASK) >>
> +		      CLK_TSADC_TSEN_SEL_SHIFT;
> +		if (sel == CLK_TSADC_TSEN_SEL_24M)
> +			prate = OSC_HZ;
> +		else
> +			prate = 100 * MHz;
> +		return DIV_TO_RATE(prate, div);
> +	case CLK_TSADC:
> +		con = readl(&cru->clksel_con[51]);
> +		div = (con & CLK_TSADC_DIV_MASK) >> CLK_TSADC_DIV_SHIFT;
> +		prate = rk3568_adc_get_clk(priv, CLK_TSADC_TSEN);
> +		return DIV_TO_RATE(prate, div);
> +	default:
> +		return -ENOENT;
> +	}
> +}
> +
> +static ulong rk3568_adc_set_clk(struct rk3568_clk_priv *priv,
> +				ulong clk_id, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int src_clk_div;
> +	ulong prate = 0;
> +
> +	switch (clk_id) {
> +	case CLK_SARADC:
> +		return OSC_HZ;
> +	case CLK_TSADC_TSEN:
> +		if (!(OSC_HZ % rate)) {
> +			src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
> +			assert(src_clk_div - 1 <= 7);
> +			rk_clrsetreg(&cru->clksel_con[51],
> +				     CLK_TSADC_TSEN_SEL_MASK |
> +				     CLK_TSADC_TSEN_DIV_MASK,
> +				     (CLK_TSADC_TSEN_SEL_24M <<
> +				      CLK_TSADC_TSEN_SEL_SHIFT) |
> +				     (src_clk_div - 1) <<
> +				     CLK_TSADC_TSEN_DIV_SHIFT);
> +		} else {
> +			src_clk_div = DIV_ROUND_UP(100 * MHz, rate);
> +			assert(src_clk_div - 1 <= 7);
> +			rk_clrsetreg(&cru->clksel_con[51],
> +				     CLK_TSADC_TSEN_SEL_MASK |
> +				     CLK_TSADC_TSEN_DIV_MASK,
> +				     (CLK_TSADC_TSEN_SEL_100M <<
> +				      CLK_TSADC_TSEN_SEL_SHIFT) |
> +				     (src_clk_div - 1) <<
> +				     CLK_TSADC_TSEN_DIV_SHIFT);
> +		}
> +		break;
> +	case CLK_TSADC:
> +			prate = rk3568_adc_get_clk(priv, CLK_TSADC_TSEN);
> +			src_clk_div = DIV_ROUND_UP(prate, rate);
> +			assert(src_clk_div - 1 <= 128);
> +			rk_clrsetreg(&cru->clksel_con[51],
> +				     CLK_TSADC_DIV_MASK,
> +				     (src_clk_div - 1) << CLK_TSADC_DIV_SHIFT);
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +	return rk3568_adc_get_clk(priv, clk_id);
> +}
> +
> +static ulong rk3568_crypto_get_rate(struct rk3568_clk_priv *priv, ulong clk_id)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 sel, con;
> +
> +	switch (clk_id) {
> +	case ACLK_SECURE_FLASH:
> +	case ACLK_CRYPTO_NS:
> +		con = readl(&cru->clksel_con[27]);
> +		sel = (con & ACLK_SECURE_FLASH_SEL_MASK) >>
> +		      ACLK_SECURE_FLASH_SEL_SHIFT;
> +		if (sel == ACLK_SECURE_FLASH_SEL_200M)
> +			return 200 * MHz;
> +		else if (sel == ACLK_SECURE_FLASH_SEL_150M)
> +			return 150 * MHz;
> +		else if (sel == ACLK_SECURE_FLASH_SEL_100M)
> +			return 100 * MHz;
> +		else
> +			return 24 * MHz;
> +	case HCLK_SECURE_FLASH:
> +	case HCLK_CRYPTO_NS:
> +	case CLK_CRYPTO_NS_RNG:
> +		con = readl(&cru->clksel_con[27]);
> +		sel = (con & HCLK_SECURE_FLASH_SEL_MASK) >>
> +		      HCLK_SECURE_FLASH_SEL_SHIFT;
> +		if (sel == HCLK_SECURE_FLASH_SEL_150M)
> +			return 150 * MHz;
> +		else if (sel == HCLK_SECURE_FLASH_SEL_100M)
> +			return 100 * MHz;
> +		else if (sel == HCLK_SECURE_FLASH_SEL_75M)
> +			return 75 * MHz;
> +		else
> +			return 24 * MHz;
> +	case CLK_CRYPTO_NS_CORE:
> +		con = readl(&cru->clksel_con[27]);
> +		sel = (con & CLK_CRYPTO_CORE_SEL_MASK) >>
> +		      CLK_CRYPTO_CORE_SEL_SHIFT;
> +		if (sel == CLK_CRYPTO_CORE_SEL_200M)
> +			return 200 * MHz;
> +		else if (sel == CLK_CRYPTO_CORE_SEL_150M)
> +			return 150 * MHz;
> +		else
> +			return 100 * MHz;
> +	case CLK_CRYPTO_NS_PKA:
> +		con = readl(&cru->clksel_con[27]);
> +		sel = (con & CLK_CRYPTO_PKA_SEL_MASK) >>
> +		      CLK_CRYPTO_PKA_SEL_SHIFT;
> +		if (sel == CLK_CRYPTO_PKA_SEL_300M)
> +			return 300 * MHz;
> +		else if (sel == CLK_CRYPTO_PKA_SEL_200M)
> +			return 200 * MHz;
> +		else
> +			return 100 * MHz;
> +	default:
> +		return -ENOENT;
> +	}
> +}
> +
> +static ulong rk3568_crypto_set_rate(struct rk3568_clk_priv *priv,
> +				    ulong clk_id, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 src_clk, mask, shift;
> +
> +	switch (clk_id) {
> +	case ACLK_SECURE_FLASH:
> +	case ACLK_CRYPTO_NS:
> +		mask = ACLK_SECURE_FLASH_SEL_MASK;
> +		shift = ACLK_SECURE_FLASH_SEL_SHIFT;
> +		if (rate == 200 * MHz)
> +			src_clk = ACLK_SECURE_FLASH_SEL_200M;
> +		else if (rate == 150 * MHz)
> +			src_clk = ACLK_SECURE_FLASH_SEL_150M;
> +		else if (rate == 100 * MHz)
> +			src_clk = ACLK_SECURE_FLASH_SEL_100M;
> +		else
> +			src_clk = ACLK_SECURE_FLASH_SEL_24M;
> +		break;
> +	case HCLK_SECURE_FLASH:
> +	case HCLK_CRYPTO_NS:
> +	case CLK_CRYPTO_NS_RNG:
> +		mask = HCLK_SECURE_FLASH_SEL_MASK;
> +		shift = HCLK_SECURE_FLASH_SEL_SHIFT;
> +		if (rate == 150 * MHz)
> +			src_clk = HCLK_SECURE_FLASH_SEL_150M;
> +		else if (rate == 100 * MHz)
> +			src_clk = HCLK_SECURE_FLASH_SEL_100M;
> +		else if (rate == 75 * MHz)
> +			src_clk = HCLK_SECURE_FLASH_SEL_75M;
> +		else
> +			src_clk = HCLK_SECURE_FLASH_SEL_24M;
> +		break;
> +	case CLK_CRYPTO_NS_CORE:
> +		mask = CLK_CRYPTO_CORE_SEL_MASK;
> +		shift = CLK_CRYPTO_CORE_SEL_SHIFT;
> +		if (rate == 200 * MHz)
> +			src_clk = CLK_CRYPTO_CORE_SEL_200M;
> +		else if (rate == 150 * MHz)
> +			src_clk = CLK_CRYPTO_CORE_SEL_150M;
> +		else
> +			src_clk = CLK_CRYPTO_CORE_SEL_100M;
> +		break;
> +	case CLK_CRYPTO_NS_PKA:
> +		mask = CLK_CRYPTO_PKA_SEL_MASK;
> +		shift = CLK_CRYPTO_PKA_SEL_SHIFT;
> +		if (rate == 300 * MHz)
> +			src_clk = CLK_CRYPTO_PKA_SEL_300M;
> +		else if (rate == 200 * MHz)
> +			src_clk = CLK_CRYPTO_PKA_SEL_200M;
> +		else
> +			src_clk = CLK_CRYPTO_PKA_SEL_100M;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	rk_clrsetreg(&cru->clksel_con[27], mask, src_clk << shift);
> +
> +	return rk3568_crypto_get_rate(priv, clk_id);
> +}
> +
> +static ulong rk3568_sdmmc_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 sel, con;
> +
> +	switch (clk_id) {
> +	case HCLK_SDMMC0:
> +	case CLK_SDMMC0:
> +		con = readl(&cru->clksel_con[30]);
> +		sel = (con & CLK_SDMMC0_SEL_MASK) >> CLK_SDMMC0_SEL_SHIFT;
> +		break;
> +	case CLK_SDMMC1:
> +		con = readl(&cru->clksel_con[30]);
> +		sel = (con & CLK_SDMMC1_SEL_MASK) >> CLK_SDMMC1_SEL_SHIFT;
> +		break;
> +	case CLK_SDMMC2:
> +		con = readl(&cru->clksel_con[32]);
> +		sel = (con & CLK_SDMMC2_SEL_MASK) >> CLK_SDMMC2_SEL_SHIFT;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	switch (sel) {
> +	case CLK_SDMMC_SEL_24M:
> +		return OSC_HZ;
> +	case CLK_SDMMC_SEL_400M:
> +		return 400 * MHz;
> +	case CLK_SDMMC_SEL_300M:
> +		return 300 * MHz;
> +	case CLK_SDMMC_SEL_100M:
> +		return 100 * MHz;
> +	case CLK_SDMMC_SEL_50M:
> +		return 50 * MHz;
> +	case CLK_SDMMC_SEL_750K:
> +		return 750 * KHz;
> +	default:
> +		return -ENOENT;
> +	}
> +}
> +
> +static ulong rk3568_sdmmc_set_clk(struct rk3568_clk_priv *priv,
> +				  ulong clk_id, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int src_clk;
> +
> +	switch (rate) {
> +	case OSC_HZ:
> +		src_clk = CLK_SDMMC_SEL_24M;
> +		break;
> +	case 400 * MHz:
> +		src_clk = CLK_SDMMC_SEL_400M;
> +		break;
> +	case 300 * MHz:
> +		src_clk = CLK_SDMMC_SEL_300M;
> +		break;
> +	case 100 * MHz:
> +		src_clk = CLK_SDMMC_SEL_100M;
> +		break;
> +	case 52 * MHz:
> +	case 50 * MHz:
> +		src_clk = CLK_SDMMC_SEL_50M;
> +		break;
> +	case 750 * KHz:
> +	case 400 * KHz:
> +		src_clk = CLK_SDMMC_SEL_750K;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	switch (clk_id) {
> +	case HCLK_SDMMC0:
> +	case CLK_SDMMC0:
> +		rk_clrsetreg(&cru->clksel_con[30],
> +			     CLK_SDMMC0_SEL_MASK,
> +			     src_clk << CLK_SDMMC0_SEL_SHIFT);
> +		break;
> +	case CLK_SDMMC1:
> +		rk_clrsetreg(&cru->clksel_con[30],
> +			     CLK_SDMMC1_SEL_MASK,
> +			     src_clk << CLK_SDMMC1_SEL_SHIFT);
> +		break;
> +	case CLK_SDMMC2:
> +		rk_clrsetreg(&cru->clksel_con[32],
> +			     CLK_SDMMC2_SEL_MASK,
> +			     src_clk << CLK_SDMMC2_SEL_SHIFT);
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return rk3568_sdmmc_get_clk(priv, clk_id);
> +}
> +
> +static ulong rk3568_sfc_get_clk(struct rk3568_clk_priv *priv)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 sel, con;
> +
> +	con = readl(&cru->clksel_con[28]);
> +	sel = (con & SCLK_SFC_SEL_MASK) >> SCLK_SFC_SEL_SHIFT;
> +	switch (sel) {
> +	case SCLK_SFC_SEL_24M:
> +		return OSC_HZ;
> +	case SCLK_SFC_SEL_50M:
> +		return 50 * MHz;
> +	case SCLK_SFC_SEL_75M:
> +		return 75 * MHz;
> +	case SCLK_SFC_SEL_100M:
> +		return 100 * MHz;
> +	case SCLK_SFC_SEL_125M:
> +		return 125 * MHz;
> +	case SCLK_SFC_SEL_150M:
> +		return 150 * KHz;
> +	default:
> +		return -ENOENT;
> +	}
> +}
> +
> +static ulong rk3568_sfc_set_clk(struct rk3568_clk_priv *priv, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int src_clk;
> +
> +	switch (rate) {
> +	case OSC_HZ:
> +		src_clk = SCLK_SFC_SEL_24M;
> +		break;
> +	case 50 * MHz:
> +		src_clk = SCLK_SFC_SEL_50M;
> +		break;
> +	case 75 * MHz:
> +		src_clk = SCLK_SFC_SEL_75M;
> +		break;
> +	case 100 * MHz:
> +		src_clk = SCLK_SFC_SEL_100M;
> +		break;
> +	case 125 * MHz:
> +		src_clk = SCLK_SFC_SEL_125M;
> +		break;
> +	case 150 * KHz:
> +		src_clk = SCLK_SFC_SEL_150M;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	rk_clrsetreg(&cru->clksel_con[28],
> +		     SCLK_SFC_SEL_MASK,
> +		     src_clk << SCLK_SFC_SEL_SHIFT);
> +
> +	return rk3568_sfc_get_clk(priv);
> +}
> +
> +static ulong rk3568_nand_get_clk(struct rk3568_clk_priv *priv)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 sel, con;
> +
> +	con = readl(&cru->clksel_con[28]);
> +	sel = (con & NCLK_NANDC_SEL_MASK) >> NCLK_NANDC_SEL_SHIFT;
> +	switch (sel) {
> +	case NCLK_NANDC_SEL_200M:
> +		return 200 * MHz;
> +	case NCLK_NANDC_SEL_150M:
> +		return 150 * MHz;
> +	case NCLK_NANDC_SEL_100M:
> +		return 100 * MHz;
> +	case NCLK_NANDC_SEL_24M:
> +		return OSC_HZ;
> +	default:
> +		return -ENOENT;
> +	}
> +}
> +
> +static ulong rk3568_nand_set_clk(struct rk3568_clk_priv *priv, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int src_clk;
> +
> +	switch (rate) {
> +	case OSC_HZ:
> +		src_clk = NCLK_NANDC_SEL_24M;
> +		break;
> +	case 100 * MHz:
> +		src_clk = NCLK_NANDC_SEL_100M;
> +		break;
> +	case 150 * MHz:
> +		src_clk = NCLK_NANDC_SEL_150M;
> +		break;
> +	case 200 * MHz:
> +		src_clk = NCLK_NANDC_SEL_200M;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	rk_clrsetreg(&cru->clksel_con[28],
> +		     NCLK_NANDC_SEL_MASK,
> +		     src_clk << NCLK_NANDC_SEL_SHIFT);
> +
> +	return rk3568_nand_get_clk(priv);
> +}
> +
> +static ulong rk3568_emmc_get_clk(struct rk3568_clk_priv *priv)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 sel, con;
> +
> +	con = readl(&cru->clksel_con[28]);
> +	sel = (con & CCLK_EMMC_SEL_MASK) >> CCLK_EMMC_SEL_SHIFT;
> +	switch (sel) {
> +	case CCLK_EMMC_SEL_200M:
> +		return 200 * MHz;
> +	case CCLK_EMMC_SEL_150M:
> +		return 150 * MHz;
> +	case CCLK_EMMC_SEL_100M:
> +		return 100 * MHz;
> +	case CCLK_EMMC_SEL_50M:
> +		return 50 * MHz;
> +	case CCLK_EMMC_SEL_375K:
> +		return 375 * KHz;
> +	case CCLK_EMMC_SEL_24M:
> +		return OSC_HZ;
> +	default:
> +		return -ENOENT;
> +	}
> +}
> +
> +static ulong rk3568_emmc_set_clk(struct rk3568_clk_priv *priv, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int src_clk;
> +
> +	switch (rate) {
> +	case OSC_HZ:
> +		src_clk = CCLK_EMMC_SEL_24M;
> +		break;
> +	case 52 * MHz:
> +	case 50 * MHz:
> +		src_clk = CCLK_EMMC_SEL_50M;
> +		break;
> +	case 100 * MHz:
> +		src_clk = CCLK_EMMC_SEL_100M;
> +		break;
> +	case 150 * MHz:
> +		src_clk = CCLK_EMMC_SEL_150M;
> +		break;
> +	case 200 * MHz:
> +		src_clk = CCLK_EMMC_SEL_200M;
> +		break;
> +	case 400 * KHz:
> +	case 375 * KHz:
> +		src_clk = CCLK_EMMC_SEL_375K;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	rk_clrsetreg(&cru->clksel_con[28],
> +		     CCLK_EMMC_SEL_MASK,
> +		     src_clk << CCLK_EMMC_SEL_SHIFT);
> +
> +	return rk3568_emmc_get_clk(priv);
> +}
> +
> +#ifndef CONFIG_SPL_BUILD
> +static ulong rk3568_aclk_vop_get_clk(struct rk3568_clk_priv *priv)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 div, sel, con, parent;
> +
> +	con = readl(&cru->clksel_con[38]);
> +	div = (con & ACLK_VOP_PRE_DIV_MASK) >> ACLK_VOP_PRE_DIV_SHIFT;
> +	sel = (con & ACLK_VOP_PRE_SEL_MASK) >> ACLK_VOP_PRE_SEL_SHIFT;
> +	if (sel == ACLK_VOP_PRE_SEL_GPLL)
> +		parent = priv->gpll_hz;
> +	else if (sel == ACLK_VOP_PRE_SEL_CPLL)
> +		parent = priv->cpll_hz;
> +	else if (sel == ACLK_VOP_PRE_SEL_VPLL)
> +		parent = priv->vpll_hz;
> +	else
> +		parent = priv->hpll_hz;
> +
> +	return DIV_TO_RATE(parent, div);
> +}
> +
> +static ulong rk3568_aclk_vop_set_clk(struct rk3568_clk_priv *priv, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int src_clk_div, src_clk_mux;
> +
> +	if ((priv->cpll_hz % rate) == 0) {
> +		src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
> +		src_clk_mux = ACLK_VOP_PRE_SEL_CPLL;
> +	} else {
> +		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
> +		src_clk_mux = ACLK_VOP_PRE_SEL_GPLL;
> +	}
> +	assert(src_clk_div - 1 <= 31);
> +	rk_clrsetreg(&cru->clksel_con[38],
> +		     ACLK_VOP_PRE_SEL_MASK | ACLK_VOP_PRE_DIV_MASK,
> +		     src_clk_mux << ACLK_VOP_PRE_SEL_SHIFT |
> +		     (src_clk_div - 1) << ACLK_VOP_PRE_DIV_SHIFT);
> +
> +	return rk3568_aclk_vop_get_clk(priv);
> +}
> +
> +static ulong rk3568_dclk_vop_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 conid, div, sel, con, parent;
> +
> +	switch (clk_id) {
> +	case DCLK_VOP0:
> +		conid = 39;
> +		break;
> +	case DCLK_VOP1:
> +		conid = 40;
> +		break;
> +	case DCLK_VOP2:
> +		conid = 41;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	con = readl(&cru->clksel_con[conid]);
> +	div = (con & DCLK0_VOP_DIV_MASK) >> DCLK0_VOP_DIV_SHIFT;
> +	sel = (con & DCLK0_VOP_SEL_MASK) >> DCLK0_VOP_SEL_SHIFT;
> +	if (sel == DCLK_VOP_SEL_HPLL)
> +		parent = rk3568_pmu_pll_get_rate(priv, HPLL);
> +	else if (sel == DCLK_VOP_SEL_VPLL)
> +		parent = rockchip_pll_get_rate(&rk3568_pll_clks[VPLL],
> +					       priv->cru, VPLL);
> +	else if (sel == DCLK_VOP_SEL_GPLL)
> +		parent = priv->gpll_hz;
> +	else if (sel == DCLK_VOP_SEL_CPLL)
> +		parent = priv->cpll_hz;
> +	else
> +		return -ENOENT;
> +
> +	return DIV_TO_RATE(parent, div);
> +}
> +
> +#define RK3568_VOP_PLL_LIMIT_FREQ 600000000
> +
> +static ulong rk3568_dclk_vop_set_clk(struct rk3568_clk_priv *priv,
> +				     ulong clk_id, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	ulong pll_rate, now, best_rate = 0;
> +	u32 i, conid, con, sel, div, best_div = 0, best_sel = 0;
> +
> +	switch (clk_id) {
> +	case DCLK_VOP0:
> +		conid = 39;
> +		break;
> +	case DCLK_VOP1:
> +		conid = 40;
> +		break;
> +	case DCLK_VOP2:
> +		conid = 41;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	con = readl(&cru->clksel_con[conid]);
> +	sel = (con & DCLK0_VOP_SEL_MASK) >> DCLK0_VOP_SEL_SHIFT;
> +
> +	if (sel == DCLK_VOP_SEL_HPLL) {
> +		div = 1;
> +		rk_clrsetreg(&cru->clksel_con[conid],
> +			     DCLK0_VOP_DIV_MASK | DCLK0_VOP_SEL_MASK,
> +			     (DCLK_VOP_SEL_HPLL << DCLK0_VOP_SEL_SHIFT) |
> +			     ((div - 1) << DCLK0_VOP_DIV_SHIFT));
> +		rk3568_pmu_pll_set_rate(priv, HPLL, div * rate);
> +	} else if (sel == DCLK_VOP_SEL_VPLL) {
> +		div = DIV_ROUND_UP(RK3568_VOP_PLL_LIMIT_FREQ, rate);
> +		rk_clrsetreg(&cru->clksel_con[conid],
> +			     DCLK0_VOP_DIV_MASK | DCLK0_VOP_SEL_MASK,
> +			     (DCLK_VOP_SEL_VPLL << DCLK0_VOP_SEL_SHIFT) |
> +			     ((div - 1) << DCLK0_VOP_DIV_SHIFT));
> +		rockchip_pll_set_rate(&rk3568_pll_clks[VPLL],
> +				      priv->cru, VPLL, div * rate);
> +	} else {
> +		for (i = 0; i <= DCLK_VOP_SEL_CPLL; i++) {
> +			switch (i) {
> +			case DCLK_VOP_SEL_GPLL:
> +				pll_rate = priv->gpll_hz;
> +				break;
> +			case DCLK_VOP_SEL_CPLL:
> +				pll_rate = priv->cpll_hz;
> +				break;
> +			default:
> +				printf("do not support this vop pll sel\n");
> +				return -EINVAL;
> +			}
> +
> +			div = DIV_ROUND_UP(pll_rate, rate);
> +			if (div > 255)
> +				continue;
> +			now = pll_rate / div;
> +			if (abs(rate - now) < abs(rate - best_rate)) {
> +				best_rate = now;
> +				best_div = div;
> +				best_sel = i;
> +			}
> +			debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
> +			      pll_rate, best_rate, best_div, best_sel);
> +		}
> +
> +		if (best_rate) {
> +			rk_clrsetreg(&cru->clksel_con[conid],
> +				     DCLK0_VOP_DIV_MASK | DCLK0_VOP_SEL_MASK,
> +				     best_sel << DCLK0_VOP_SEL_SHIFT |
> +				     (best_div - 1) << DCLK0_VOP_DIV_SHIFT);
> +		} else {
> +			printf("do not support this vop freq %lu\n", rate);
> +			return -EINVAL;
> +		}
> +	}
> +	return rk3568_dclk_vop_get_clk(priv, clk_id);
> +}
> +
> +static ulong rk3568_gmac_src_get_clk(struct rk3568_clk_priv *priv,
> +				     ulong mac_id)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 sel, con;
> +
> +	con = readl(&cru->clksel_con[31 + mac_id * 2]);
> +	sel = (con & CLK_MAC0_2TOP_SEL_MASK) >> CLK_MAC0_2TOP_SEL_SHIFT;
> +
> +	switch (sel) {
> +	case CLK_MAC0_2TOP_SEL_125M:
> +		return 125 * MHz;
> +	case CLK_MAC0_2TOP_SEL_50M:
> +		return 50 * MHz;
> +	case CLK_MAC0_2TOP_SEL_25M:
> +		return 25 * MHz;
> +	case CLK_MAC0_2TOP_SEL_PPLL:
> +		return rk3568_pmu_pll_get_rate(priv, HPLL);
> +	default:
> +		return -ENOENT;
> +	}
> +}
> +
> +static ulong rk3568_gmac_src_set_clk(struct rk3568_clk_priv *priv,
> +				     ulong mac_id, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int src_clk;
> +
> +	switch (rate) {
> +	case 125 * MHz:
> +		src_clk = CLK_MAC0_2TOP_SEL_125M;
> +		break;
> +	case 50 * MHz:
> +		src_clk = CLK_MAC0_2TOP_SEL_50M;
> +		break;
> +	case 25 * MHz:
> +		src_clk = CLK_MAC0_2TOP_SEL_25M;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2],
> +		     CLK_MAC0_2TOP_SEL_MASK,
> +		     src_clk << CLK_MAC0_2TOP_SEL_SHIFT);
> +
> +	return rk3568_gmac_src_get_clk(priv, mac_id);
> +}
> +
> +static ulong rk3568_gmac_out_get_clk(struct rk3568_clk_priv *priv,
> +				     ulong mac_id)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 sel, con;
> +
> +	con = readl(&cru->clksel_con[31 + mac_id * 2]);
> +	sel = (con & CLK_MAC0_OUT_SEL_MASK) >> CLK_MAC0_OUT_SEL_SHIFT;
> +
> +	switch (sel) {
> +	case CLK_MAC0_OUT_SEL_125M:
> +		return 125 * MHz;
> +	case CLK_MAC0_OUT_SEL_50M:
> +		return 50 * MHz;
> +	case CLK_MAC0_OUT_SEL_25M:
> +		return 25 * MHz;
> +	case CLK_MAC0_OUT_SEL_24M:
> +		return OSC_HZ;
> +	default:
> +		return -ENOENT;
> +	}
> +}
> +
> +static ulong rk3568_gmac_out_set_clk(struct rk3568_clk_priv *priv,
> +				     ulong mac_id, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int src_clk;
> +
> +	switch (rate) {
> +	case 125 * MHz:
> +		src_clk = CLK_MAC0_OUT_SEL_125M;
> +		break;
> +	case 50 * MHz:
> +		src_clk = CLK_MAC0_OUT_SEL_50M;
> +		break;
> +	case 25 * MHz:
> +		src_clk = CLK_MAC0_OUT_SEL_25M;
> +		break;
> +	case 24 * MHz:
> +		src_clk = CLK_MAC0_OUT_SEL_24M;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2],
> +		     CLK_MAC0_OUT_SEL_MASK,
> +		     src_clk << CLK_MAC0_OUT_SEL_SHIFT);
> +
> +	return rk3568_gmac_out_get_clk(priv, mac_id);
> +}
> +
> +static ulong rk3568_gmac_ptp_ref_get_clk(struct rk3568_clk_priv *priv,
> +					 ulong mac_id)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 sel, con;
> +
> +	con = readl(&cru->clksel_con[31 + mac_id * 2]);
> +	sel = (con & CLK_GMAC0_PTP_REF_SEL_MASK) >> CLK_GMAC0_PTP_REF_SEL_SHIFT;
> +
> +	switch (sel) {
> +	case CLK_GMAC0_PTP_REF_SEL_62_5M:
> +		return 62500 * KHz;
> +	case CLK_GMAC0_PTP_REF_SEL_100M:
> +		return 100 * MHz;
> +	case CLK_GMAC0_PTP_REF_SEL_50M:
> +		return 50 * MHz;
> +	case CLK_GMAC0_PTP_REF_SEL_24M:
> +		return OSC_HZ;
> +	default:
> +		return -ENOENT;
> +	}
> +}
> +
> +static ulong rk3568_gmac_ptp_ref_set_clk(struct rk3568_clk_priv *priv,
> +					 ulong mac_id, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int src_clk;
> +
> +	switch (rate) {
> +	case 62500 * KHz:
> +		src_clk = CLK_GMAC0_PTP_REF_SEL_62_5M;
> +		break;
> +	case 100 * MHz:
> +		src_clk = CLK_GMAC0_PTP_REF_SEL_100M;
> +		break;
> +	case 50 * MHz:
> +		src_clk = CLK_GMAC0_PTP_REF_SEL_50M;
> +		break;
> +	case 24 * MHz:
> +		src_clk = CLK_GMAC0_PTP_REF_SEL_24M;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2],
> +		     CLK_GMAC0_PTP_REF_SEL_MASK,
> +		     src_clk << CLK_GMAC0_PTP_REF_SEL_SHIFT);
> +
> +	return rk3568_gmac_ptp_ref_get_clk(priv, mac_id);
> +}
> +
> +static ulong rk3568_gmac_tx_rx_set_clk(struct rk3568_clk_priv *priv,
> +				       ulong mac_id, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 con, sel, div_sel;
> +
> +	con = readl(&cru->clksel_con[31 + mac_id * 2]);
> +	sel = (con & RMII0_MODE_MASK) >> RMII0_MODE_SHIFT;
> +
> +	if (sel == RMII0_MODE_SEL_RGMII) {
> +		if (rate == 2500000)
> +			div_sel = RGMII0_CLK_SEL_2_5M;
> +		else if (rate == 25000000)
> +			div_sel = RGMII0_CLK_SEL_25M;
> +		else
> +			div_sel = RGMII0_CLK_SEL_125M;
> +		rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2],
> +			     RGMII0_CLK_SEL_MASK,
> +			     div_sel << RGMII0_CLK_SEL_SHIFT);
> +	} else if (sel == RMII0_MODE_SEL_RMII) {
> +		if (rate == 2500000)
> +			div_sel = RMII0_CLK_SEL_2_5M;
> +		else
> +			div_sel = RMII0_CLK_SEL_25M;
> +		rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2],
> +			     RMII0_CLK_SEL_MASK,
> +			     div_sel << RMII0_CLK_SEL_SHIFT);
> +	}
> +
> +	return 0;
> +}
> +
> +static ulong rk3568_ebc_get_clk(struct rk3568_clk_priv *priv)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 con, div, p_rate;
> +
> +	con = readl(&cru->clksel_con[79]);
> +	div = (con & CPLL_333M_DIV_MASK) >> CPLL_333M_DIV_SHIFT;
> +	p_rate = DIV_TO_RATE(priv->cpll_hz, div);
> +
> +	con = readl(&cru->clksel_con[43]);
> +	div = (con & DCLK_EBC_SEL_MASK) >> DCLK_EBC_SEL_SHIFT;
> +	switch (div) {
> +	case DCLK_EBC_SEL_GPLL_400M:
> +		return 400 * MHz;
> +	case DCLK_EBC_SEL_CPLL_333M:
> +		return p_rate;
> +	case DCLK_EBC_SEL_GPLL_200M:
> +		return 200 * MHz;
> +	default:
> +		return -ENOENT;
> +	}
> +}
> +
> +static ulong rk3568_ebc_set_clk(struct rk3568_clk_priv *priv, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int src_clk_div;
> +
> +	src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
> +	assert(src_clk_div - 1 <= 31);
> +	rk_clrsetreg(&cru->clksel_con[79],
> +		     CPLL_333M_DIV_MASK,
> +		     (src_clk_div - 1) << CPLL_333M_DIV_SHIFT);
> +	rk_clrsetreg(&cru->clksel_con[43],
> +		     DCLK_EBC_SEL_MASK,
> +		     DCLK_EBC_SEL_CPLL_333M << DCLK_EBC_SEL_SHIFT);
> +
> +	return rk3568_ebc_get_clk(priv);
> +}
> +
> +static ulong rk3568_rkvdec_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 con, div, src, p_rate;
> +
> +	switch (clk_id) {
> +	case ACLK_RKVDEC_PRE:
> +	case ACLK_RKVDEC:
> +		con = readl(&cru->clksel_con[47]);
> +		src = (con & ACLK_RKVDEC_SEL_MASK) >> ACLK_RKVDEC_SEL_SHIFT;
> +		div = (con & ACLK_RKVDEC_DIV_MASK) >> ACLK_RKVDEC_DIV_SHIFT;
> +		if (src == ACLK_RKVDEC_SEL_CPLL)
> +			p_rate = priv->cpll_hz;
> +		else
> +			p_rate = priv->gpll_hz;
> +		return DIV_TO_RATE(p_rate, div);
> +	case CLK_RKVDEC_CORE:
> +		con = readl(&cru->clksel_con[49]);
> +		src = (con & CLK_RKVDEC_CORE_SEL_MASK)
> +		      >> CLK_RKVDEC_CORE_SEL_SHIFT;
> +		div = (con & CLK_RKVDEC_CORE_DIV_MASK)
> +		      >> CLK_RKVDEC_CORE_DIV_SHIFT;
> +		if (src == CLK_RKVDEC_CORE_SEL_CPLL)
> +			p_rate = priv->cpll_hz;
> +		else if (src == CLK_RKVDEC_CORE_SEL_NPLL)
> +			p_rate = priv->npll_hz;
> +		else if (src == CLK_RKVDEC_CORE_SEL_VPLL)
> +			p_rate = priv->vpll_hz;
> +		else
> +			p_rate = priv->gpll_hz;
> +		return DIV_TO_RATE(p_rate, div);
> +	default:
> +		return -ENOENT;
> +	}
> +}
> +
> +static ulong rk3568_rkvdec_set_clk(struct rk3568_clk_priv *priv,
> +				   ulong clk_id, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	int src_clk_div, src, p_rate;
> +
> +	switch (clk_id) {
> +	case ACLK_RKVDEC_PRE:
> +	case ACLK_RKVDEC:
> +		src = (readl(&cru->clksel_con[47]) & ACLK_RKVDEC_SEL_MASK)
> +		      >> ACLK_RKVDEC_SEL_SHIFT;
> +		if (src == ACLK_RKVDEC_SEL_CPLL)
> +			p_rate = priv->cpll_hz;
> +		else
> +			p_rate = priv->gpll_hz;
> +		src_clk_div = DIV_ROUND_UP(p_rate, rate);
> +		assert(src_clk_div - 1 <= 31);
> +		rk_clrsetreg(&cru->clksel_con[47],
> +			     ACLK_RKVDEC_SEL_MASK |
> +			     ACLK_RKVDEC_DIV_MASK,
> +			     (src << ACLK_RKVDEC_SEL_SHIFT) |
> +			     (src_clk_div - 1) << ACLK_RKVDEC_DIV_SHIFT);
> +		break;
> +	case CLK_RKVDEC_CORE:
> +		src = (readl(&cru->clksel_con[49]) & CLK_RKVDEC_CORE_SEL_MASK)
> +		      >> CLK_RKVDEC_CORE_SEL_SHIFT;
> +		if (src == CLK_RKVDEC_CORE_SEL_CPLL)
> +			p_rate = priv->cpll_hz;
> +		else if (src == CLK_RKVDEC_CORE_SEL_NPLL)
> +			p_rate = priv->npll_hz;
> +		else if (src == CLK_RKVDEC_CORE_SEL_VPLL)
> +			p_rate = priv->vpll_hz;
> +		else
> +			p_rate = priv->gpll_hz;
> +		src_clk_div = DIV_ROUND_UP(p_rate, rate);
> +		assert(src_clk_div - 1 <= 31);
> +		rk_clrsetreg(&cru->clksel_con[49],
> +			     CLK_RKVDEC_CORE_SEL_MASK |
> +			     CLK_RKVDEC_CORE_DIV_MASK,
> +			     (src << CLK_RKVDEC_CORE_SEL_SHIFT) |
> +			     (src_clk_div - 1) << CLK_RKVDEC_CORE_DIV_SHIFT);
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return rk3568_rkvdec_get_clk(priv, clk_id);
> +}
> +
> +static ulong rk3568_uart_get_rate(struct rk3568_clk_priv *priv, ulong clk_id)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 reg, con, fracdiv, div, src, p_src, p_rate;
> +	unsigned long m, n;
> +
> +	switch (clk_id) {
> +	case SCLK_UART1:
> +		reg = 52;
> +		break;
> +	case SCLK_UART2:
> +		reg = 54;
> +		break;
> +	case SCLK_UART3:
> +		reg = 56;
> +		break;
> +	case SCLK_UART4:
> +		reg = 58;
> +		break;
> +	case SCLK_UART5:
> +		reg = 60;
> +		break;
> +	case SCLK_UART6:
> +		reg = 62;
> +		break;
> +	case SCLK_UART7:
> +		reg = 64;
> +		break;
> +	case SCLK_UART8:
> +		reg = 66;
> +		break;
> +	case SCLK_UART9:
> +		reg = 68;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +	con = readl(&cru->clksel_con[reg]);
> +	src = (con & CLK_UART_SEL_MASK) >> CLK_UART_SEL_SHIFT;
> +	div = (con & CLK_UART_SRC_DIV_MASK) >> CLK_UART_SRC_DIV_SHIFT;
> +	p_src = (con & CLK_UART_SRC_SEL_MASK) >> CLK_UART_SRC_SEL_SHIFT;
> +	if (p_src == CLK_UART_SRC_SEL_GPLL)
> +		p_rate = priv->gpll_hz;
> +	else if (p_src == CLK_UART_SRC_SEL_CPLL)
> +		p_rate = priv->cpll_hz;
> +	else
> +		p_rate = 480000000;
> +	if (src == CLK_UART_SEL_SRC) {
> +		return DIV_TO_RATE(p_rate, div);
> +	} else if (src == CLK_UART_SEL_FRAC) {
> +		fracdiv = readl(&cru->clksel_con[reg + 1]);
> +		n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
> +		n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
> +		m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
> +		m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
> +		return DIV_TO_RATE(p_rate, div) * n / m;
> +	} else {
> +		return OSC_HZ;
> +	}
> +}
> +
> +static ulong rk3568_uart_set_rate(struct rk3568_clk_priv *priv,
> +				  ulong clk_id, ulong rate)
> +{
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 reg, clk_src, uart_src, div;
> +	unsigned long m = 0, n = 0, val;
> +
> +	if (priv->gpll_hz % rate == 0) {
> +		clk_src = CLK_UART_SRC_SEL_GPLL;
> +		uart_src = CLK_UART_SEL_SRC;
> +		div = DIV_ROUND_UP(priv->gpll_hz, rate);
> +	} else if (priv->cpll_hz % rate == 0) {
> +		clk_src = CLK_UART_SRC_SEL_CPLL;
> +		uart_src = CLK_UART_SEL_SRC;
> +		div = DIV_ROUND_UP(priv->gpll_hz, rate);
> +	} else if (rate == OSC_HZ) {
> +		clk_src = CLK_UART_SRC_SEL_GPLL;
> +		uart_src = CLK_UART_SEL_XIN24M;
> +		div = 2;
> +	} else {
> +		clk_src = CLK_UART_SRC_SEL_GPLL;
> +		uart_src = CLK_UART_SEL_FRAC;
> +		div = 2;
> +		rational_best_approximation(rate, priv->gpll_hz / div,
> +					    GENMASK(16 - 1, 0),
> +					    GENMASK(16 - 1, 0),
> +					    &m, &n);
> +	}
> +
> +	switch (clk_id) {
> +	case SCLK_UART1:
> +		reg = 52;
> +		break;
> +	case SCLK_UART2:
> +		reg = 54;
> +		break;
> +	case SCLK_UART3:
> +		reg = 56;
> +		break;
> +	case SCLK_UART4:
> +		reg = 58;
> +		break;
> +	case SCLK_UART5:
> +		reg = 60;
> +		break;
> +	case SCLK_UART6:
> +		reg = 62;
> +		break;
> +	case SCLK_UART7:
> +		reg = 64;
> +		break;
> +	case SCLK_UART8:
> +		reg = 66;
> +		break;
> +	case SCLK_UART9:
> +		reg = 68;
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +	rk_clrsetreg(&cru->clksel_con[reg],
> +		     CLK_UART_SEL_MASK | CLK_UART_SRC_SEL_MASK |
> +		     CLK_UART_SRC_DIV_MASK,
> +		     (clk_src << CLK_UART_SRC_SEL_SHIFT) |
> +		     (uart_src << CLK_UART_SEL_SHIFT) |
> +		     ((div - 1) << CLK_UART_SRC_DIV_SHIFT));
> +	if (m && n) {
> +		val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
> +		writel(val, &cru->clksel_con[reg + 1]);
> +	}
> +
> +	return rk3568_uart_get_rate(priv, clk_id);
> +}
> +#endif
> +
> +static ulong rk3568_clk_get_rate(struct clk *clk)
> +{
> +	struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
> +	ulong rate = 0;
> +
> +	if (!priv->gpll_hz) {
> +		printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
> +		return -ENOENT;
> +	}
> +
> +	switch (clk->id) {
> +	case PLL_APLL:
> +	case ARMCLK:
> +		rate = rockchip_pll_get_rate(&rk3568_pll_clks[APLL], priv->cru,
> +					     APLL);
> +		break;
> +	case PLL_CPLL:
> +		rate = rockchip_pll_get_rate(&rk3568_pll_clks[CPLL], priv->cru,
> +					     CPLL);
> +		break;
> +	case PLL_GPLL:
> +		rate = rockchip_pll_get_rate(&rk3568_pll_clks[GPLL], priv->cru,
> +					     GPLL);
> +		break;
> +	case PLL_NPLL:
> +		rate = rockchip_pll_get_rate(&rk3568_pll_clks[NPLL], priv->cru,
> +					     NPLL);
> +		break;
> +	case PLL_VPLL:
> +		rate = rockchip_pll_get_rate(&rk3568_pll_clks[VPLL], priv->cru,
> +					     VPLL);
> +		break;
> +	case PLL_DPLL:
> +		rate = rockchip_pll_get_rate(&rk3568_pll_clks[DPLL], priv->cru,
> +					     DPLL);
> +		break;
> +	case ACLK_BUS:
> +	case PCLK_BUS:
> +	case PCLK_WDT_NS:
> +		rate = rk3568_bus_get_clk(priv, clk->id);
> +		break;
> +	case ACLK_PERIMID:
> +	case HCLK_PERIMID:
> +		rate = rk3568_perimid_get_clk(priv, clk->id);
> +		break;
> +	case ACLK_TOP_HIGH:
> +	case ACLK_TOP_LOW:
> +	case HCLK_TOP:
> +	case PCLK_TOP:
> +		rate = rk3568_top_get_clk(priv, clk->id);
> +		break;
> +	case CLK_I2C1:
> +	case CLK_I2C2:
> +	case CLK_I2C3:
> +	case CLK_I2C4:
> +	case CLK_I2C5:
> +		rate = rk3568_i2c_get_clk(priv, clk->id);
> +		break;
> +	case CLK_SPI0:
> +	case CLK_SPI1:
> +	case CLK_SPI2:
> +	case CLK_SPI3:
> +		rate = rk3568_spi_get_clk(priv, clk->id);
> +		break;
> +	case CLK_PWM1:
> +	case CLK_PWM2:
> +	case CLK_PWM3:
> +		rate = rk3568_pwm_get_clk(priv, clk->id);
> +		break;
> +	case CLK_SARADC:
> +	case CLK_TSADC_TSEN:
> +	case CLK_TSADC:
> +		rate = rk3568_adc_get_clk(priv, clk->id);
> +		break;
> +	case HCLK_SDMMC0:
> +	case CLK_SDMMC0:
> +	case CLK_SDMMC1:
> +	case CLK_SDMMC2:
> +		rate = rk3568_sdmmc_get_clk(priv, clk->id);
> +		break;
> +	case SCLK_SFC:
> +		rate = rk3568_sfc_get_clk(priv);
> +		break;
> +	case NCLK_NANDC:
> +		rate = rk3568_nand_get_clk(priv);
> +		break;
> +	case CCLK_EMMC:
> +		rate = rk3568_emmc_get_clk(priv);
> +		break;
> +#ifndef CONFIG_SPL_BUILD
> +	case ACLK_VOP:
> +		rate = rk3568_aclk_vop_get_clk(priv);
> +		break;
> +	case DCLK_VOP0:
> +	case DCLK_VOP1:
> +	case DCLK_VOP2:
> +		rate = rk3568_dclk_vop_get_clk(priv, clk->id);
> +		break;
> +	case SCLK_GMAC0:
> +	case CLK_MAC0_2TOP:
> +	case CLK_MAC0_REFOUT:
> +		rate = rk3568_gmac_src_get_clk(priv, 0);
> +		break;
> +	case CLK_MAC0_OUT:
> +		rate = rk3568_gmac_out_get_clk(priv, 0);
> +		break;
> +	case CLK_GMAC0_PTP_REF:
> +		rate = rk3568_gmac_ptp_ref_get_clk(priv, 0);
> +		break;
> +	case SCLK_GMAC1:
> +	case CLK_MAC1_2TOP:
> +	case CLK_MAC1_REFOUT:
> +		rate = rk3568_gmac_src_get_clk(priv, 1);
> +		break;
> +	case CLK_MAC1_OUT:
> +		rate = rk3568_gmac_out_get_clk(priv, 1);
> +		break;
> +	case CLK_GMAC1_PTP_REF:
> +		rate = rk3568_gmac_ptp_ref_get_clk(priv, 1);
> +		break;
> +	case DCLK_EBC:
> +		rate = rk3568_ebc_get_clk(priv);
> +		break;
> +	case ACLK_RKVDEC_PRE:
> +	case ACLK_RKVDEC:
> +	case CLK_RKVDEC_CORE:
> +		rate = rk3568_rkvdec_get_clk(priv, clk->id);
> +		break;
> +	case TCLK_WDT_NS:
> +		rate = OSC_HZ;
> +		break;
> +	case SCLK_UART1:
> +	case SCLK_UART2:
> +	case SCLK_UART3:
> +	case SCLK_UART4:
> +	case SCLK_UART5:
> +	case SCLK_UART6:
> +	case SCLK_UART7:
> +	case SCLK_UART8:
> +	case SCLK_UART9:
> +		rate = rk3568_uart_get_rate(priv, clk->id);
> +		break;
> +#endif
> +	case ACLK_SECURE_FLASH:
> +	case ACLK_CRYPTO_NS:
> +	case HCLK_SECURE_FLASH:
> +	case HCLK_CRYPTO_NS:
> +	case CLK_CRYPTO_NS_RNG:
> +	case CLK_CRYPTO_NS_CORE:
> +	case CLK_CRYPTO_NS_PKA:
> +		rate = rk3568_crypto_get_rate(priv, clk->id);
> +		break;
> +	case CPLL_500M:
> +	case CPLL_333M:
> +	case CPLL_250M:
> +	case CPLL_125M:
> +	case CPLL_100M:
> +	case CPLL_62P5M:
> +	case CPLL_50M:
> +	case CPLL_25M:
> +		rate = rk3568_cpll_div_get_rate(priv, clk->id);
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return rate;
> +};
> +
> +static ulong rk3568_clk_set_rate(struct clk *clk, ulong rate)
> +{
> +	struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
> +	ulong ret = 0;
> +
> +	if (!priv->gpll_hz) {
> +		printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
> +		return -ENOENT;
> +	}
> +
> +	switch (clk->id) {
> +	case PLL_APLL:
> +	case ARMCLK:
> +		if (priv->armclk_hz)
> +			rk3568_armclk_set_clk(priv, rate);
> +		priv->armclk_hz = rate;
> +		break;
> +	case PLL_CPLL:
> +		ret = rockchip_pll_set_rate(&rk3568_pll_clks[CPLL], priv->cru,
> +					    CPLL, rate);
> +		priv->cpll_hz = rockchip_pll_get_rate(&rk3568_pll_clks[CPLL],
> +						      priv->cru, CPLL);
> +		break;
> +	case PLL_GPLL:
> +		ret = rockchip_pll_set_rate(&rk3568_pll_clks[GPLL], priv->cru,
> +					    GPLL, rate);
> +		priv->gpll_hz = rockchip_pll_get_rate(&rk3568_pll_clks[GPLL],
> +						      priv->cru, GPLL);
> +		break;
> +	case PLL_NPLL:
> +		ret = rockchip_pll_set_rate(&rk3568_pll_clks[NPLL], priv->cru,
> +					    NPLL, rate);
> +		break;
> +	case PLL_VPLL:
> +		ret = rockchip_pll_set_rate(&rk3568_pll_clks[VPLL], priv->cru,
> +					    VPLL, rate);
> +		priv->vpll_hz = rockchip_pll_get_rate(&rk3568_pll_clks[VPLL],
> +						      priv->cru,
> +						      VPLL);
> +		break;
> +	case ACLK_BUS:
> +	case PCLK_BUS:
> +	case PCLK_WDT_NS:
> +		ret = rk3568_bus_set_clk(priv, clk->id, rate);
> +		break;
> +	case ACLK_PERIMID:
> +	case HCLK_PERIMID:
> +		ret = rk3568_perimid_set_clk(priv, clk->id, rate);
> +		break;
> +	case ACLK_TOP_HIGH:
> +	case ACLK_TOP_LOW:
> +	case HCLK_TOP:
> +	case PCLK_TOP:
> +		ret = rk3568_top_set_clk(priv, clk->id, rate);
> +		break;
> +	case CLK_I2C1:
> +	case CLK_I2C2:
> +	case CLK_I2C3:
> +	case CLK_I2C4:
> +	case CLK_I2C5:
> +		ret = rk3568_i2c_set_clk(priv, clk->id, rate);
> +		break;
> +	case CLK_SPI0:
> +	case CLK_SPI1:
> +	case CLK_SPI2:
> +	case CLK_SPI3:
> +		ret = rk3568_spi_set_clk(priv, clk->id, rate);
> +		break;
> +	case CLK_PWM1:
> +	case CLK_PWM2:
> +	case CLK_PWM3:
> +		ret = rk3568_pwm_set_clk(priv, clk->id, rate);
> +		break;
> +	case CLK_SARADC:
> +	case CLK_TSADC_TSEN:
> +	case CLK_TSADC:
> +		ret = rk3568_adc_set_clk(priv, clk->id, rate);
> +		break;
> +	case HCLK_SDMMC0:
> +	case CLK_SDMMC0:
> +	case CLK_SDMMC1:
> +	case CLK_SDMMC2:
> +		ret = rk3568_sdmmc_set_clk(priv, clk->id, rate);
> +		break;
> +	case SCLK_SFC:
> +		ret = rk3568_sfc_set_clk(priv, rate);
> +		break;
> +	case NCLK_NANDC:
> +		ret = rk3568_nand_set_clk(priv, rate);
> +		break;
> +	case CCLK_EMMC:
> +		ret = rk3568_emmc_set_clk(priv, rate);
> +		break;
> +#ifndef CONFIG_SPL_BUILD
> +	case ACLK_VOP:
> +		ret = rk3568_aclk_vop_set_clk(priv, rate);
> +		break;
> +	case DCLK_VOP0:
> +	case DCLK_VOP1:
> +	case DCLK_VOP2:
> +		ret = rk3568_dclk_vop_set_clk(priv, clk->id, rate);
> +		break;
> +	case SCLK_GMAC0:
> +	case CLK_MAC0_2TOP:
> +	case CLK_MAC0_REFOUT:
> +		ret = rk3568_gmac_src_set_clk(priv, 0, rate);
> +		break;
> +	case CLK_MAC0_OUT:
> +		ret = rk3568_gmac_out_set_clk(priv, 0, rate);
> +		break;
> +	case SCLK_GMAC0_RX_TX:
> +		ret = rk3568_gmac_tx_rx_set_clk(priv, 0, rate);
> +		break;
> +	case CLK_GMAC0_PTP_REF:
> +		ret = rk3568_gmac_ptp_ref_set_clk(priv, 0, rate);
> +		break;
> +	case SCLK_GMAC1:
> +	case CLK_MAC1_2TOP:
> +	case CLK_MAC1_REFOUT:
> +		ret = rk3568_gmac_src_set_clk(priv, 1, rate);
> +		break;
> +	case CLK_MAC1_OUT:
> +		ret = rk3568_gmac_out_set_clk(priv, 1, rate);
> +		break;
> +	case SCLK_GMAC1_RX_TX:
> +		ret = rk3568_gmac_tx_rx_set_clk(priv, 1, rate);
> +		break;
> +	case CLK_GMAC1_PTP_REF:
> +		ret = rk3568_gmac_ptp_ref_set_clk(priv, 1, rate);
> +		break;
> +	case DCLK_EBC:
> +		ret = rk3568_ebc_set_clk(priv, rate);
> +		break;
> +	case ACLK_RKVDEC_PRE:
> +	case ACLK_RKVDEC:
> +	case CLK_RKVDEC_CORE:
> +		ret = rk3568_rkvdec_set_clk(priv, clk->id, rate);


I don't thing we need to set rkvdec clock in the U-Boot, pls remove it.

Thanks,

- Kever

> +		break;
> +	case TCLK_WDT_NS:
> +		ret = OSC_HZ;
> +		break;
> +	case SCLK_UART1:
> +	case SCLK_UART2:
> +	case SCLK_UART3:
> +	case SCLK_UART4:
> +	case SCLK_UART5:
> +	case SCLK_UART6:
> +	case SCLK_UART7:
> +	case SCLK_UART8:
> +	case SCLK_UART9:
> +		ret = rk3568_uart_set_rate(priv, clk->id, rate);
> +		break;
> +#endif
> +	case ACLK_SECURE_FLASH:
> +	case ACLK_CRYPTO_NS:
> +	case HCLK_SECURE_FLASH:
> +	case HCLK_CRYPTO_NS:
> +	case CLK_CRYPTO_NS_RNG:
> +	case CLK_CRYPTO_NS_CORE:
> +	case CLK_CRYPTO_NS_PKA:
> +		ret = rk3568_crypto_set_rate(priv, clk->id, rate);
> +		break;
> +	case CPLL_500M:
> +	case CPLL_333M:
> +	case CPLL_250M:
> +	case CPLL_125M:
> +	case CPLL_100M:
> +	case CPLL_62P5M:
> +	case CPLL_50M:
> +	case CPLL_25M:
> +		ret = rk3568_cpll_div_set_rate(priv, clk->id, rate);
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return ret;
> +};
> +
> +#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
> +static int rk3568_gmac0_src_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
> +	struct rk3568_cru *cru = priv->cru;
> +
> +	if (parent->id == CLK_MAC0_2TOP)
> +		rk_clrsetreg(&cru->clksel_con[31],
> +			     RMII0_EXTCLK_SEL_MASK,
> +			     RMII0_EXTCLK_SEL_MAC0_TOP <<
> +			     RMII0_EXTCLK_SEL_SHIFT);
> +	else
> +		rk_clrsetreg(&cru->clksel_con[31],
> +			     RMII0_EXTCLK_SEL_MASK,
> +			     RMII0_EXTCLK_SEL_IO << RMII0_EXTCLK_SEL_SHIFT);
> +	return 0;
> +}
> +
> +static int rk3568_gmac1_src_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
> +	struct rk3568_cru *cru = priv->cru;
> +
> +	if (parent->id == CLK_MAC1_2TOP)
> +		rk_clrsetreg(&cru->clksel_con[33],
> +			     RMII0_EXTCLK_SEL_MASK,
> +			     RMII0_EXTCLK_SEL_MAC0_TOP <<
> +			     RMII0_EXTCLK_SEL_SHIFT);
> +	else
> +		rk_clrsetreg(&cru->clksel_con[33],
> +			     RMII0_EXTCLK_SEL_MASK,
> +			     RMII0_EXTCLK_SEL_IO << RMII0_EXTCLK_SEL_SHIFT);
> +	return 0;
> +}
> +
> +static int rk3568_gmac0_tx_rx_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
> +	struct rk3568_cru *cru = priv->cru;
> +
> +	if (parent->id == SCLK_GMAC0_RGMII_SPEED)
> +		rk_clrsetreg(&cru->clksel_con[31],
> +			     RMII0_MODE_MASK,
> +			     RMII0_MODE_SEL_RGMII << RMII0_MODE_SHIFT);
> +	else if (parent->id == SCLK_GMAC0_RMII_SPEED)
> +		rk_clrsetreg(&cru->clksel_con[31],
> +			     RMII0_MODE_MASK,
> +			     RMII0_MODE_SEL_RMII << RMII0_MODE_SHIFT);
> +	else
> +		rk_clrsetreg(&cru->clksel_con[31],
> +			     RMII0_MODE_MASK,
> +			     RMII0_MODE_SEL_GMII << RMII0_MODE_SHIFT);
> +
> +	return 0;
> +}
> +
> +static int rk3568_gmac1_tx_rx_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
> +	struct rk3568_cru *cru = priv->cru;
> +
> +	if (parent->id == SCLK_GMAC1_RGMII_SPEED)
> +		rk_clrsetreg(&cru->clksel_con[33],
> +			     RMII0_MODE_MASK,
> +			     RMII0_MODE_SEL_RGMII << RMII0_MODE_SHIFT);
> +	else if (parent->id == SCLK_GMAC1_RMII_SPEED)
> +		rk_clrsetreg(&cru->clksel_con[33],
> +			     RMII0_MODE_MASK,
> +			     RMII0_MODE_SEL_RMII << RMII0_MODE_SHIFT);
> +	else
> +		rk_clrsetreg(&cru->clksel_con[33],
> +			     RMII0_MODE_MASK,
> +			     RMII0_MODE_SEL_GMII << RMII0_MODE_SHIFT);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused rk3568_dclk_vop_set_parent(struct clk *clk,
> +						     struct clk *parent)
> +{
> +	struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 con_id;
> +
> +	switch (clk->id) {
> +	case DCLK_VOP0:
> +		con_id = 39;
> +		break;
> +	case DCLK_VOP1:
> +		con_id = 40;
> +		break;
> +	case DCLK_VOP2:
> +		con_id = 41;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	if (parent->id == PLL_VPLL) {
> +		rk_clrsetreg(&cru->clksel_con[con_id], DCLK0_VOP_SEL_MASK,
> +			     DCLK_VOP_SEL_VPLL << DCLK0_VOP_SEL_SHIFT);
> +	} else {
> +		rk_clrsetreg(&cru->clksel_con[con_id], DCLK0_VOP_SEL_MASK,
> +			     DCLK_VOP_SEL_HPLL << DCLK0_VOP_SEL_SHIFT);
> +	}
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused rk3568_rkvdec_set_parent(struct clk *clk,
> +						   struct clk *parent)
> +{
> +	struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
> +	struct rk3568_cru *cru = priv->cru;
> +	u32 con_id, mask, shift;
> +
> +	switch (clk->id) {
> +	case ACLK_RKVDEC_PRE:
> +		con_id = 47;
> +		mask = ACLK_RKVDEC_SEL_MASK;
> +		shift = ACLK_RKVDEC_SEL_SHIFT;
> +		break;
> +	case CLK_RKVDEC_CORE:
> +		con_id = 49;
> +		mask = CLK_RKVDEC_CORE_SEL_MASK;
> +		shift = CLK_RKVDEC_CORE_SEL_SHIFT;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	if (parent->id == PLL_CPLL) {
> +		rk_clrsetreg(&cru->clksel_con[con_id], mask,
> +			     ACLK_RKVDEC_SEL_CPLL << shift);
> +	} else {
> +		rk_clrsetreg(&cru->clksel_con[con_id], mask,
> +			     ACLK_RKVDEC_SEL_GPLL << shift);
> +	}
> +
> +	return 0;
> +}
> +
> +static int rk3568_clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	switch (clk->id) {
> +	case SCLK_GMAC0:
> +		return rk3568_gmac0_src_set_parent(clk, parent);
> +	case SCLK_GMAC1:
> +		return rk3568_gmac1_src_set_parent(clk, parent);
> +	case SCLK_GMAC0_RX_TX:
> +		return rk3568_gmac0_tx_rx_set_parent(clk, parent);
> +	case SCLK_GMAC1_RX_TX:
> +		return rk3568_gmac1_tx_rx_set_parent(clk, parent);
> +	case DCLK_VOP0:
> +	case DCLK_VOP1:
> +	case DCLK_VOP2:
> +		return rk3568_dclk_vop_set_parent(clk, parent);
> +	case ACLK_RKVDEC_PRE:
> +	case CLK_RKVDEC_CORE:
> +		return rk3568_rkvdec_set_parent(clk, parent);
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return 0;
> +}
> +#endif
> +
> +static struct clk_ops rk3568_clk_ops = {
> +	.get_rate = rk3568_clk_get_rate,
> +	.set_rate = rk3568_clk_set_rate,
> +#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
> +	.set_parent = rk3568_clk_set_parent,
> +#endif
> +};
> +
> +static void rk3568_clk_init(struct rk3568_clk_priv *priv)
> +{
> +	int ret;
> +
> +	priv->sync_kernel = false;
> +	if (!priv->armclk_enter_hz) {
> +		priv->armclk_enter_hz =
> +			rockchip_pll_get_rate(&rk3568_pll_clks[APLL],
> +					      priv->cru, APLL);
> +		priv->armclk_init_hz = priv->armclk_enter_hz;
> +	}
> +
> +	if (priv->armclk_init_hz != APLL_HZ) {
> +		ret = rk3568_armclk_set_clk(priv, APLL_HZ);
> +		if (!ret)
> +			priv->armclk_init_hz = APLL_HZ;
> +	}
> +	if (priv->cpll_hz != CPLL_HZ) {
> +		ret = rockchip_pll_set_rate(&rk3568_pll_clks[CPLL], priv->cru,
> +					    CPLL, CPLL_HZ);
> +		if (!ret)
> +			priv->cpll_hz = CPLL_HZ;
> +	}
> +	if (priv->gpll_hz != GPLL_HZ) {
> +		ret = rockchip_pll_set_rate(&rk3568_pll_clks[GPLL], priv->cru,
> +					    GPLL, GPLL_HZ);
> +		if (!ret)
> +			priv->gpll_hz = GPLL_HZ;
> +	}
> +
> +#ifdef CONFIG_SPL_BUILD
> +	ret = rk3568_bus_set_clk(priv, ACLK_BUS, 150000000);
> +	if (ret < 0)
> +		printf("Fail to set the ACLK_BUS clock.\n");
> +#endif
> +
> +	priv->ppll_hz = rk3568_pmu_pll_get_rate(priv, PPLL);
> +	priv->hpll_hz = rk3568_pmu_pll_get_rate(priv, HPLL);
> +}
> +
> +static int rk3568_clk_probe(struct udevice *dev)
> +{
> +	struct rk3568_clk_priv *priv = dev_get_priv(dev);
> +	int ret;
> +
> +	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
> +	if (IS_ERR(priv->grf))
> +		return PTR_ERR(priv->grf);
> +
> +	rk3568_clk_init(priv);
> +
> +	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
> +	ret = clk_set_defaults(dev, 1);
> +	if (ret)
> +		debug("%s clk_set_defaults failed %d\n", __func__, ret);
> +	else
> +		priv->sync_kernel = true;
> +
> +	return 0;
> +}
> +
> +static int rk3568_clk_ofdata_to_platdata(struct udevice *dev)
> +{
> +	struct rk3568_clk_priv *priv = dev_get_priv(dev);
> +
> +	priv->cru = dev_read_addr_ptr(dev);
> +
> +	return 0;
> +}
> +
> +static int rk3568_clk_bind(struct udevice *dev)
> +{
> +	int ret;
> +	struct udevice *sys_child;
> +	struct sysreset_reg *priv;
> +
> +	/* The reset driver does not have a device node, so bind it here */
> +	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
> +				 &sys_child);
> +	if (ret) {
> +		debug("Warning: No sysreset driver: ret=%d\n", ret);
> +	} else {
> +		priv = malloc(sizeof(struct sysreset_reg));
> +		priv->glb_srst_fst_value = offsetof(struct rk3568_cru,
> +						    glb_srst_fst);
> +		priv->glb_srst_snd_value = offsetof(struct rk3568_cru,
> +						    glb_srsr_snd);
> +	}
> +
> +#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
> +	ret = offsetof(struct rk3568_cru, softrst_con[0]);
> +	ret = rockchip_reset_bind(dev, ret, 30);
> +	if (ret)
> +		debug("Warning: software reset driver bind faile\n");
> +#endif
> +
> +	return 0;
> +}
> +
> +static const struct udevice_id rk3568_clk_ids[] = {
> +	{ .compatible = "rockchip,rk3568-cru" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(rockchip_rk3568_cru) = {
> +	.name		= "rockchip_rk3568_cru",
> +	.id		= UCLASS_CLK,
> +	.of_match	= rk3568_clk_ids,
> +	.priv_auto = sizeof(struct rk3568_clk_priv),
> +	.of_to_plat = rk3568_clk_ofdata_to_platdata,
> +	.ops		= &rk3568_clk_ops,
> +	.bind		= rk3568_clk_bind,
> +	.probe		= rk3568_clk_probe,
> +#if CONFIG_IS_ENABLED(OF_PLATDATA)
> +	.plat_auto	= sizeof(struct rk3568_clk_plat),
> +#endif
> +};



      reply	other threads:[~2021-05-21 13:34 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-19  8:49 [PATCH v1 0/2] clk: rockchip: rk3568: add clock driver Elaine at denx.de
2021-05-19  8:49 ` [PATCH v1 1/2] rockchip: rk3568: add device tree file Elaine at denx.de
2021-05-21 13:22   ` Kever Yang
2021-05-19  8:49 ` [PATCH v1 2/2] rockchip: rk3568: add clock driver Elaine at denx.de
2021-05-21 13:33   ` Kever Yang [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d005043a-72ec-f3c2-3dc6-3f592203bf3a@rock-chips.com \
    --to=kever.yang@rock-chips.com \
    --cc=chenjh@rock-chips.com \
    --cc=lukma@denx.de \
    --cc=sjg@chromium.org \
    --cc=u-boot@lists.denx.de \
    --cc=zhangqing@rock-chips.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.