[PATCH 2/3] rockchip: rk3588: Add support for sdmmc clocks in SPL

Kever Yang kever.yang at rock-chips.com
Tue Mar 21 04:13:00 CET 2023


On 2023/3/18 03:16, Jonas Karlman wrote:
> Booting from sdmmc on RK3588 currently works because of a workaround in
> the device tree, clocks are reordered so that the driver use ciu-sample
> instead of ciu, and the BootRom initializes sdmmc clocks before SPL is
> loaded into DRAM.
>
> The sdmmc clocks are normally controlled by TF-A using SCMI. However,
> there is a need to control these clocks in SPL, before TF-A has started.
>
> This adds a rk3588_scru driver to control the sdmmc clocks in SPL before
> TF-A has started, using scru regs. It also adds a small glue driver to
> bind the scmi clock node to the rk3588_scru driver in SPL.
>
> Fixes: 7a474df74023 ("clk: rockchip: Add rk3588 clk support")
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
Reviewed-by: Kever Yang <kever.yang at rock-chips.com>

Thanks,
- Kever
> ---
>   arch/arm/include/asm/arch-rockchip/clock.h    |   1 -
>   .../include/asm/arch-rockchip/cru_rk3588.h    |  19 ++-
>   drivers/clk/rockchip/clk_rk3588.c             | 125 ++++++++++++++++++
>   3 files changed, 143 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/include/asm/arch-rockchip/clock.h b/arch/arm/include/asm/arch-rockchip/clock.h
> index 90e66c7da049..f002ebcb7ac1 100644
> --- a/arch/arm/include/asm/arch-rockchip/clock.h
> +++ b/arch/arm/include/asm/arch-rockchip/clock.h
> @@ -194,6 +194,5 @@ int rockchip_get_clk(struct udevice **devp);
>    * Return: 0 success, or error value
>    */
>   int rockchip_reset_bind(struct udevice *pdev, u32 reg_offset, u32 reg_number);
> -int rockchip_get_scmi_clk(struct udevice **devp);
>   
>   #endif
> diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3588.h b/arch/arm/include/asm/arch-rockchip/cru_rk3588.h
> index 3ea59e900861..7f4a90853929 100644
> --- a/arch/arm/include/asm/arch-rockchip/cru_rk3588.h
> +++ b/arch/arm/include/asm/arch-rockchip/cru_rk3588.h
> @@ -11,12 +11,12 @@
>   #define KHz		1000
>   #define OSC_HZ		(24 * MHz)
>   
> -#define CPU_PVTPLL_HZ	(1008 * MHz)
>   #define LPLL_HZ		(816 * MHz)
>   #define GPLL_HZ		(1188 * MHz)
>   #define CPLL_HZ		(1500 * MHz)
>   #define NPLL_HZ         (850 * MHz)
>   #define PPLL_HZ		(1100 * MHz)
> +#define SPLL_HZ		(702 * MHz)
>   
>   /* RK3588 pll id */
>   enum rk3588_pll_id {
> @@ -447,5 +447,22 @@ enum {
>   	CLK_I2C0_SEL_MASK			= 1 << CLK_I2C0_SEL_SHIFT,
>   	CLK_I2C_SEL_200M			= 0,
>   	CLK_I2C_SEL_100M,
> +
> +	/* SECURECRU_CLKSEL_CON01 */
> +	SCMI_HCLK_SD_SEL_SHIFT			= 2,
> +	SCMI_HCLK_SD_SEL_MASK			= 3 << SCMI_HCLK_SD_SEL_SHIFT,
> +	SCMI_HCLK_SD_SEL_150M			= 0,
> +	SCMI_HCLK_SD_SEL_100M,
> +	SCMI_HCLK_SD_SEL_50M,
> +	SCMI_HCLK_SD_SEL_24M,
> +
> +	/* SECURECRU_CLKSEL_CON03 */
> +	SCMI_CCLK_SD_SEL_SHIFT			= 12,
> +	SCMI_CCLK_SD_SEL_MASK			= 3 << SCMI_CCLK_SD_SEL_SHIFT,
> +	SCMI_CCLK_SD_SEL_GPLL			= 0,
> +	SCMI_CCLK_SD_SEL_SPLL,
> +	SCMI_CCLK_SD_SEL_24M,
> +	SCMI_CCLK_SD_DIV_SHIFT			= 6,
> +	SCMI_CCLK_SD_DIV_MASK			= 0x3f << SCMI_CCLK_SD_DIV_SHIFT,
>   };
>   #endif
> diff --git a/drivers/clk/rockchip/clk_rk3588.c b/drivers/clk/rockchip/clk_rk3588.c
> index a7df553e8750..41e31b61a55b 100644
> --- a/drivers/clk/rockchip/clk_rk3588.c
> +++ b/drivers/clk/rockchip/clk_rk3588.c
> @@ -9,6 +9,7 @@
>   #include <clk-uclass.h>
>   #include <dm.h>
>   #include <errno.h>
> +#include <scmi_protocols.h>
>   #include <syscon.h>
>   #include <asm/arch-rockchip/cru_rk3588.h>
>   #include <asm/arch-rockchip/clock.h>
> @@ -1994,3 +1995,127 @@ U_BOOT_DRIVER(rockchip_rk3588_cru) = {
>   	.bind		= rk3588_clk_bind,
>   	.probe		= rk3588_clk_probe,
>   };
> +
> +#ifdef CONFIG_SPL_BUILD
> +#define SCRU_BASE			0xfd7d0000
> +
> +static ulong rk3588_scru_clk_get_rate(struct clk *clk)
> +{
> +	u32 con, div, sel, parent;
> +
> +	switch (clk->id) {
> +	case SCMI_CCLK_SD:
> +		con = readl(SCRU_BASE + RK3588_CLKSEL_CON(3));
> +		sel = (con & SCMI_CCLK_SD_SEL_MASK) >> SCMI_CCLK_SD_SEL_SHIFT;
> +		div = (con & SCMI_CCLK_SD_DIV_MASK) >> SCMI_CCLK_SD_DIV_SHIFT;
> +		if (sel == SCMI_CCLK_SD_SEL_GPLL)
> +			parent = GPLL_HZ;
> +		else if (sel == SCMI_CCLK_SD_SEL_SPLL)
> +			parent = SPLL_HZ;
> +		else
> +			parent = OSC_HZ;
> +		return DIV_TO_RATE(parent, div);
> +	case SCMI_HCLK_SD:
> +		con = readl(SCRU_BASE + RK3588_CLKSEL_CON(1));
> +		sel = (con & SCMI_HCLK_SD_SEL_MASK) >> SCMI_HCLK_SD_SEL_SHIFT;
> +		if (sel == SCMI_HCLK_SD_SEL_150M)
> +			return 150 * MHz;
> +		else if (sel == SCMI_HCLK_SD_SEL_100M)
> +			return 100 * MHz;
> +		else if (sel == SCMI_HCLK_SD_SEL_50M)
> +			return 50 * MHz;
> +		else
> +			return OSC_HZ;
> +	default:
> +		return -ENOENT;
> +	}
> +}
> +
> +static ulong rk3588_scru_clk_set_rate(struct clk *clk, ulong rate)
> +{
> +	u32 div, sel;
> +
> +	switch (clk->id) {
> +	case SCMI_CCLK_SD:
> +		if ((OSC_HZ % rate) == 0) {
> +			sel = SCMI_CCLK_SD_SEL_24M;
> +			div = DIV_ROUND_UP(OSC_HZ, rate);
> +		} else if ((SPLL_HZ % rate) == 0) {
> +			sel = SCMI_CCLK_SD_SEL_SPLL;
> +			div = DIV_ROUND_UP(SPLL_HZ, rate);
> +		} else {
> +			sel = SCMI_CCLK_SD_SEL_GPLL;
> +			div = DIV_ROUND_UP(GPLL_HZ, rate);
> +		}
> +		rk_clrsetreg(SCRU_BASE + RK3588_CLKSEL_CON(3),
> +			     SCMI_CCLK_SD_SEL_MASK | SCMI_CCLK_SD_DIV_MASK,
> +			     sel << SCMI_CCLK_SD_SEL_SHIFT |
> +			     (div - 1) << SCMI_CCLK_SD_DIV_SHIFT);
> +		break;
> +	case SCMI_HCLK_SD:
> +		if (rate >= 150 * MHz)
> +			sel = SCMI_HCLK_SD_SEL_150M;
> +		else if (rate >= 100 * MHz)
> +			sel = SCMI_HCLK_SD_SEL_100M;
> +		else if (rate >= 50 * MHz)
> +			sel = SCMI_HCLK_SD_SEL_50M;
> +		else
> +			sel = SCMI_HCLK_SD_SEL_24M;
> +		rk_clrsetreg(SCRU_BASE + RK3588_CLKSEL_CON(1),
> +			     SCMI_HCLK_SD_SEL_MASK,
> +			     sel << SCMI_HCLK_SD_SEL_SHIFT);
> +		break;
> +	default:
> +		return -ENOENT;
> +	}
> +
> +	return rk3588_scru_clk_get_rate(clk);
> +}
> +
> +static const struct clk_ops rk3588_scru_clk_ops = {
> +	.get_rate = rk3588_scru_clk_get_rate,
> +	.set_rate = rk3588_scru_clk_set_rate,
> +};
> +
> +U_BOOT_DRIVER(rockchip_rk3588_scru) = {
> +	.name = "rockchip_rk3588_scru",
> +	.id = UCLASS_CLK,
> +	.ops = &rk3588_scru_clk_ops,
> +};
> +
> +static int rk3588_scmi_spl_glue_bind(struct udevice *dev)
> +{
> +	ofnode node;
> +	u32 protocol_id;
> +	const char *name;
> +
> +	dev_for_each_subnode(node, dev) {
> +		if (!ofnode_is_enabled(node))
> +			continue;
> +
> +		if (ofnode_read_u32(node, "reg", &protocol_id))
> +			continue;
> +
> +		if (protocol_id != SCMI_PROTOCOL_ID_CLOCK)
> +			continue;
> +
> +		name = ofnode_get_name(node);
> +		return device_bind_driver_to_node(dev, "rockchip_rk3588_scru",
> +						  name, node, NULL);
> +	}
> +
> +	return -ENOENT;
> +}
> +
> +static const struct udevice_id rk3588_scmi_spl_glue_ids[] = {
> +	{ .compatible = "arm,scmi-smc" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(rk3588_scmi_spl_glue) = {
> +	.name		= "rk3588_scmi_spl_glue",
> +	.id		= UCLASS_NOP,
> +	.of_match	= rk3588_scmi_spl_glue_ids,
> +	.bind		= rk3588_scmi_spl_glue_bind,
> +};
> +#endif


More information about the U-Boot mailing list