[PATCH 07/13] clk: exynos: Add Samsung clock framework

Chanho Park chanho61.park at samsung.com
Tue Dec 19 12:38:51 CET 2023


> -----Original Message-----
> From: U-Boot <u-boot-bounces at lists.denx.de> On Behalf Of Sam Protsenko
> Sent: Wednesday, December 13, 2023 12:17 PM
> To: Minkyu Kang <mk7.kang at samsung.com>; Tom Rini <trini at konsulko.com>;
> Lukasz Majewski <lukma at denx.de>; Sean Anderson <seanga2 at gmail.com>
> Cc: Simon Glass <sjg at chromium.org>; Heinrich Schuchardt
> <xypron.glpk at gmx.de>; u-boot at lists.denx.de
> Subject: [PATCH 07/13] clk: exynos: Add Samsung clock framework
> 
> Heavily based on Linux kernel Samsung clock framework, with some changes
> to accommodate the differences in U-Boot CCF implementation. It's also
> quite minimal as compared to the Linux version.
> 
> Signed-off-by: Sam Protsenko <semen.protsenko at linaro.org>
> ---
>  drivers/clk/exynos/Makefile  |   9 +-
>  drivers/clk/exynos/clk-pll.c | 167 +++++++++++++++++++++++++
>  drivers/clk/exynos/clk-pll.h |  23 ++++
>  drivers/clk/exynos/clk.c     | 121 +++++++++++++++++++
>  drivers/clk/exynos/clk.h     | 228 +++++++++++++++++++++++++++++++++++
>  5 files changed, 546 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/clk/exynos/clk-pll.c
>  create mode 100644 drivers/clk/exynos/clk-pll.h
>  create mode 100644 drivers/clk/exynos/clk.c
>  create mode 100644 drivers/clk/exynos/clk.h
> 
> diff --git a/drivers/clk/exynos/Makefile b/drivers/clk/exynos/Makefile
> index 7faf238571ef..04c5b9a39e16 100644
> --- a/drivers/clk/exynos/Makefile
> +++ b/drivers/clk/exynos/Makefile
> @@ -1,6 +1,11 @@
>  # SPDX-License-Identifier: GPL-2.0+
>  #
>  # Copyright (C) 2016 Samsung Electronics
> -# Thomas Abraham <thomas.ab at samsung.com>
> +# Copyright (C) 2023 Linaro Ltd.
> +#
> +# Authors:
> +#   Thomas Abraham <thomas.ab at samsung.com>
> +#   Sam Protsenko <semen.protsenko at linaro.org>
> 
> -obj-$(CONFIG_CLK_EXYNOS7420)	+= clk-exynos7420.o
> +obj-$(CONFIG_$(SPL_TPL_)CLK_CCF)	+= clk.o clk-pll.o
> +obj-$(CONFIG_CLK_EXYNOS7420)		+= clk-exynos7420.o
> diff --git a/drivers/clk/exynos/clk-pll.c b/drivers/clk/exynos/clk-pll.c
> new file mode 100644
> index 000000000000..9e496ff83aaf
> --- /dev/null
> +++ b/drivers/clk/exynos/clk-pll.c
> @@ -0,0 +1,167 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2016 Samsung Electronics
> + * Copyright (C) 2023 Linaro Ltd.
> + *
> + * Authors:
> + *   Thomas Abraham <thomas.ab at exynos.com>

Need to correct Thomas's email to samsung.com if you want to keep his
original credit even though his e-mail was already stale since he left the
company.

> + *   Sam Protsenko <semen.protsenko at linaro.org>
> + *
> + * This file contains the utility functions to register the pll clocks.
> + */
> +
> +#include <asm/io.h>
> +#include <div64.h>
> +#include <malloc.h>
> +#include <clk-uclass.h>
> +#include <dm/device.h>
> +#include <clk.h>
> +#include "clk.h"
> +
> +#define UBOOT_DM_CLK_SAMSUNG_PLL0822X	"samsung_clk_pll0822x"
> +#define UBOOT_DM_CLK_SAMSUNG_PLL0831X	"samsung_clk_pll0831x"
> +
> +struct samsung_clk_pll {
> +	struct clk		clk;
> +	void __iomem		*con_reg;
> +	enum samsung_pll_type	type;
> +};
> +
> +#define to_clk_pll(_clk) container_of(_clk, struct samsung_clk_pll, clk)
> +
> +/*
> + * PLL0822x Clock Type
> + */
> +
> +#define PLL0822X_MDIV_MASK		0x3ff
> +#define PLL0822X_PDIV_MASK		0x3f
> +#define PLL0822X_SDIV_MASK		0x7
> +#define PLL0822X_MDIV_SHIFT		16
> +#define PLL0822X_PDIV_SHIFT		8
> +#define PLL0822X_SDIV_SHIFT		0
> +
> +static unsigned long samsung_pll0822x_recalc_rate(struct clk *clk)
> +{
> +	struct samsung_clk_pll *pll = to_clk_pll(clk);
> +	u32 mdiv, pdiv, sdiv, pll_con3;
> +	u64 fvco = clk_get_parent_rate(clk);
> +
> +	pll_con3 = readl_relaxed(pll->con_reg);
> +	mdiv = (pll_con3 >> PLL0822X_MDIV_SHIFT) & PLL0822X_MDIV_MASK;
> +	pdiv = (pll_con3 >> PLL0822X_PDIV_SHIFT) & PLL0822X_PDIV_MASK;
> +	sdiv = (pll_con3 >> PLL0822X_SDIV_SHIFT) & PLL0822X_SDIV_MASK;
> +
> +	fvco *= mdiv;
> +	do_div(fvco, (pdiv << sdiv));
> +	return (unsigned long)fvco;
> +}
> +
> +static const struct clk_ops samsung_pll0822x_clk_min_ops = {
> +	.get_rate = samsung_pll0822x_recalc_rate,
> +};
> +
> +/*
> + * PLL0831x Clock Type
> + */
> +
> +#define PLL0831X_KDIV_MASK		0xffff
> +#define PLL0831X_MDIV_MASK		0x1ff
> +#define PLL0831X_PDIV_MASK		0x3f
> +#define PLL0831X_SDIV_MASK		0x7
> +#define PLL0831X_MDIV_SHIFT		16
> +#define PLL0831X_PDIV_SHIFT		8
> +#define PLL0831X_SDIV_SHIFT		0
> +#define PLL0831X_KDIV_SHIFT		0
> +
> +static unsigned long samsung_pll0831x_recalc_rate(struct clk *clk)
> +{
> +	struct samsung_clk_pll *pll = to_clk_pll(clk);
> +	u32 mdiv, pdiv, sdiv, pll_con3, pll_con5;
> +	s16 kdiv;
> +	u64 fvco = clk_get_parent_rate(clk);
> +
> +	pll_con3 = readl_relaxed(pll->con_reg);
> +	pll_con5 = readl_relaxed(pll->con_reg + 8);
> +	mdiv = (pll_con3 >> PLL0831X_MDIV_SHIFT) & PLL0831X_MDIV_MASK;
> +	pdiv = (pll_con3 >> PLL0831X_PDIV_SHIFT) & PLL0831X_PDIV_MASK;
> +	sdiv = (pll_con3 >> PLL0831X_SDIV_SHIFT) & PLL0831X_SDIV_MASK;
> +	kdiv = (s16)((pll_con5 >> PLL0831X_KDIV_SHIFT) &
> PLL0831X_KDIV_MASK);
> +
> +	fvco *= (mdiv << 16) + kdiv;
> +	do_div(fvco, (pdiv << sdiv));
> +	fvco >>= 16;
> +
> +	return (unsigned long)fvco;
> +}
> +
> +static const struct clk_ops samsung_pll0831x_clk_min_ops = {
> +	.get_rate = samsung_pll0831x_recalc_rate,
> +};
> +
> +static struct clk *_samsung_clk_register_pll(void __iomem *base,
> +					const struct samsung_pll_clock
*pll_clk)
> +{
> +	struct samsung_clk_pll *pll;
> +	struct clk *clk;
> +	const char *drv_name;
> +	int ret;
> +
> +	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
> +	if (!pll)
> +		return ERR_PTR(-ENOMEM);
> +
> +	pll->con_reg = base + pll_clk->con_offset;
> +	pll->type = pll_clk->type;
> +	clk = &pll->clk;
> +	clk->flags = pll_clk->flags;
> +
> +	switch (pll_clk->type) {
> +	case pll_0822x:
> +		drv_name = UBOOT_DM_CLK_SAMSUNG_PLL0822X;
> +		break;
> +	case pll_0831x:
> +		drv_name = UBOOT_DM_CLK_SAMSUNG_PLL0831X;
> +		break;
> +	default:
> +		kfree(pll);
> +		return ERR_PTR(-ENODEV);
> +	}
> +
> +	ret = clk_register(clk, drv_name, pll_clk->name, pll_clk-
> >parent_name);
> +	if (ret) {
> +		kfree(pll);
> +		return ERR_PTR(ret);
> +	}
> +
> +	return clk;
> +}
> +
> +void samsung_clk_register_pll(void __iomem *base,
> +			      const struct samsung_pll_clock *clk_list,
> +			      unsigned int nr_clk)
> +{
> +	unsigned int cnt;
> +
> +	for (cnt = 0; cnt < nr_clk; cnt++) {
> +		struct clk *clk;
> +		const struct samsung_pll_clock *pll_clk;
> +
> +		pll_clk = &clk_list[cnt];
> +		clk = _samsung_clk_register_pll(base, pll_clk);
> +		clk_dm(pll_clk->id, clk);
> +	}
> +}
> +
> +U_BOOT_DRIVER(samsung_pll0822x_clk) = {
> +	.name	= UBOOT_DM_CLK_SAMSUNG_PLL0822X,
> +	.id	= UCLASS_CLK,
> +	.ops	= &samsung_pll0822x_clk_min_ops,
> +	.flags	= DM_FLAG_PRE_RELOC,
> +};
> +
> +U_BOOT_DRIVER(samsung_pll0831x_clk) = {
> +	.name	= UBOOT_DM_CLK_SAMSUNG_PLL0831X,
> +	.id	= UCLASS_CLK,
> +	.ops	= &samsung_pll0831x_clk_min_ops,
> +	.flags	= DM_FLAG_PRE_RELOC,
> +};
> diff --git a/drivers/clk/exynos/clk-pll.h b/drivers/clk/exynos/clk-pll.h
> new file mode 100644
> index 000000000000..3b477369aeb8
> --- /dev/null
> +++ b/drivers/clk/exynos/clk-pll.h
> @@ -0,0 +1,23 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2016 Samsung Electronics
> + * Copyright (C) 2023 Linaro Ltd.
> + *
> + * Authors:
> + *   Thomas Abraham <thomas.ab at exynos.com>

Ditto.

Othewise,
Reviewed-by: Chanho Park <chanho61.park at samsung.com>



More information about the U-Boot mailing list