[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