diff options
author | 2023-10-10 14:33:42 +0000 | |
---|---|---|
committer | 2023-10-10 14:33:42 +0000 | |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/drivers/clk/exynos | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/drivers/clk/exynos')
-rw-r--r-- | roms/u-boot/drivers/clk/exynos/Kconfig | 18 | ||||
-rw-r--r-- | roms/u-boot/drivers/clk/exynos/Makefile | 7 | ||||
-rw-r--r-- | roms/u-boot/drivers/clk/exynos/clk-exynos7420.c | 230 | ||||
-rw-r--r-- | roms/u-boot/drivers/clk/exynos/clk-pll.c | 32 | ||||
-rw-r--r-- | roms/u-boot/drivers/clk/exynos/clk-pll.h | 8 |
5 files changed, 295 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/clk/exynos/Kconfig b/roms/u-boot/drivers/clk/exynos/Kconfig new file mode 100644 index 000000000..eb0efa97d --- /dev/null +++ b/roms/u-boot/drivers/clk/exynos/Kconfig @@ -0,0 +1,18 @@ +config CLK_EXYNOS + bool + select CLK + help + This enables support for common clock driver API on Samsung + Exynos SoCs. + +menu "Clock drivers for Exynos SoCs" + depends on CLK_EXYNOS + +config CLK_EXYNOS7420 + bool "Clock driver for Samsung's Exynos7420 SoC" + default y + help + This enables common clock driver support for platforms based + on Samsung Exynos7420 SoC. + +endmenu diff --git a/roms/u-boot/drivers/clk/exynos/Makefile b/roms/u-boot/drivers/clk/exynos/Makefile new file mode 100644 index 000000000..c9f29c873 --- /dev/null +++ b/roms/u-boot/drivers/clk/exynos/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2016 Samsung Electronics +# Thomas Abraham <thomas.ab@samsung.com> + +obj-y += clk-pll.o +obj-$(CONFIG_CLK_EXYNOS7420) += clk-exynos7420.o diff --git a/roms/u-boot/drivers/clk/exynos/clk-exynos7420.c b/roms/u-boot/drivers/clk/exynos/clk-exynos7420.c new file mode 100644 index 000000000..7d869eb02 --- /dev/null +++ b/roms/u-boot/drivers/clk/exynos/clk-exynos7420.c @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Samsung Exynos7420 clock driver. + * Copyright (C) 2016 Samsung Electronics + * Thomas Abraham <thomas.ab@samsung.com> + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <clk-uclass.h> +#include <asm/io.h> +#include <dt-bindings/clock/exynos7420-clk.h> +#include "clk-pll.h" + +#define DIVIDER(reg, shift, mask) \ + (((readl(reg) >> shift) & mask) + 1) + +/* CMU TOPC block device structure */ +struct exynos7420_clk_cmu_topc { + unsigned int rsvd1[68]; + unsigned int bus0_pll_con[2]; + unsigned int rsvd2[2]; + unsigned int bus1_pll_con[2]; + unsigned int rsvd3[54]; + unsigned int mux_sel[6]; + unsigned int rsvd4[250]; + unsigned int div[4]; +}; + +/* CMU TOP0 block device structure */ +struct exynos7420_clk_cmu_top0 { + unsigned int rsvd0[128]; + unsigned int mux_sel[7]; + unsigned int rsvd1[261]; + unsigned int div_peric[5]; +}; + +/** + * struct exynos7420_clk_topc_priv - private data for CMU topc clock driver. + * + * @topc: base address of the memory mapped CMU TOPC controller. + * @fin_freq: frequency of the Oscillator clock. + * @sclk_bus0_pll_a: frequency of sclk_bus0_pll_a clock. + * @sclk_bus1_pll_a: frequency of sclk_bus1_pll_a clock. + */ +struct exynos7420_clk_topc_priv { + struct exynos7420_clk_cmu_topc *topc; + unsigned long fin_freq; + unsigned long sclk_bus0_pll_a; + unsigned long sclk_bus1_pll_a; +}; + +/** + * struct exynos7420_clk_top0_priv - private data for CMU top0 clock driver. + * + * @top0: base address of the memory mapped CMU TOP0 controller. + * @mout_top0_bus0_pll_half: frequency of mout_top0_bus0_pll_half clock + * @sclk_uart2: frequency of sclk_uart2 clock. + */ +struct exynos7420_clk_top0_priv { + struct exynos7420_clk_cmu_top0 *top0; + unsigned long mout_top0_bus0_pll_half; + unsigned long sclk_uart2; +}; + +static ulong exynos7420_topc_get_rate(struct clk *clk) +{ + struct exynos7420_clk_topc_priv *priv = dev_get_priv(clk->dev); + + switch (clk->id) { + case DOUT_SCLK_BUS0_PLL: + case SCLK_BUS0_PLL_A: + case SCLK_BUS0_PLL_B: + return priv->sclk_bus0_pll_a; + case DOUT_SCLK_BUS1_PLL: + case SCLK_BUS1_PLL_A: + case SCLK_BUS1_PLL_B: + return priv->sclk_bus1_pll_a; + default: + return 0; + } +} + +static struct clk_ops exynos7420_clk_topc_ops = { + .get_rate = exynos7420_topc_get_rate, +}; + +static int exynos7420_clk_topc_probe(struct udevice *dev) +{ + struct exynos7420_clk_topc_priv *priv = dev_get_priv(dev); + struct exynos7420_clk_cmu_topc *topc; + struct clk in_clk; + unsigned long rate; + fdt_addr_t base; + int ret; + + base = dev_read_addr(dev); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + topc = (struct exynos7420_clk_cmu_topc *)base; + priv->topc = topc; + + ret = clk_get_by_index(dev, 0, &in_clk); + if (ret >= 0) + priv->fin_freq = clk_get_rate(&in_clk); + + rate = pll145x_get_rate(&topc->bus0_pll_con[0], priv->fin_freq); + if (readl(&topc->mux_sel[1]) & (1 << 16)) + rate >>= 1; + rate /= DIVIDER(&topc->div[3], 0, 0xf); + priv->sclk_bus0_pll_a = rate; + + rate = pll145x_get_rate(&topc->bus1_pll_con[0], priv->fin_freq) / + DIVIDER(&topc->div[3], 8, 0xf); + priv->sclk_bus1_pll_a = rate; + + return 0; +} + +static ulong exynos7420_top0_get_rate(struct clk *clk) +{ + struct exynos7420_clk_top0_priv *priv = dev_get_priv(clk->dev); + struct exynos7420_clk_cmu_top0 *top0 = priv->top0; + + switch (clk->id) { + case CLK_SCLK_UART2: + return priv->mout_top0_bus0_pll_half / + DIVIDER(&top0->div_peric[3], 8, 0xf); + default: + return 0; + } +} + +static struct clk_ops exynos7420_clk_top0_ops = { + .get_rate = exynos7420_top0_get_rate, +}; + +static int exynos7420_clk_top0_probe(struct udevice *dev) +{ + struct exynos7420_clk_top0_priv *priv; + struct exynos7420_clk_cmu_top0 *top0; + struct clk in_clk; + fdt_addr_t base; + int ret; + + priv = dev_get_priv(dev); + if (!priv) + return -EINVAL; + + base = dev_read_addr(dev); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + top0 = (struct exynos7420_clk_cmu_top0 *)base; + priv->top0 = top0; + + ret = clk_get_by_index(dev, 1, &in_clk); + if (ret >= 0) { + priv->mout_top0_bus0_pll_half = + clk_get_rate(&in_clk); + if (readl(&top0->mux_sel[1]) & (1 << 16)) + priv->mout_top0_bus0_pll_half >>= 1; + } + + return 0; +} + +static ulong exynos7420_peric1_get_rate(struct clk *clk) +{ + struct clk in_clk; + unsigned int ret; + unsigned long freq = 0; + + switch (clk->id) { + case SCLK_UART2: + ret = clk_get_by_index(clk->dev, 3, &in_clk); + if (ret < 0) + return ret; + freq = clk_get_rate(&in_clk); + break; + } + + return freq; +} + +static struct clk_ops exynos7420_clk_peric1_ops = { + .get_rate = exynos7420_peric1_get_rate, +}; + +static const struct udevice_id exynos7420_clk_topc_compat[] = { + { .compatible = "samsung,exynos7-clock-topc" }, + { } +}; + +U_BOOT_DRIVER(exynos7420_clk_topc) = { + .name = "exynos7420-clock-topc", + .id = UCLASS_CLK, + .of_match = exynos7420_clk_topc_compat, + .probe = exynos7420_clk_topc_probe, + .priv_auto = sizeof(struct exynos7420_clk_topc_priv), + .ops = &exynos7420_clk_topc_ops, +}; + +static const struct udevice_id exynos7420_clk_top0_compat[] = { + { .compatible = "samsung,exynos7-clock-top0" }, + { } +}; + +U_BOOT_DRIVER(exynos7420_clk_top0) = { + .name = "exynos7420-clock-top0", + .id = UCLASS_CLK, + .of_match = exynos7420_clk_top0_compat, + .probe = exynos7420_clk_top0_probe, + .priv_auto = sizeof(struct exynos7420_clk_top0_priv), + .ops = &exynos7420_clk_top0_ops, +}; + +static const struct udevice_id exynos7420_clk_peric1_compat[] = { + { .compatible = "samsung,exynos7-clock-peric1" }, + { } +}; + +U_BOOT_DRIVER(exynos7420_clk_peric1) = { + .name = "exynos7420-clock-peric1", + .id = UCLASS_CLK, + .of_match = exynos7420_clk_peric1_compat, + .ops = &exynos7420_clk_peric1_ops, +}; diff --git a/roms/u-boot/drivers/clk/exynos/clk-pll.c b/roms/u-boot/drivers/clk/exynos/clk-pll.c new file mode 100644 index 000000000..407fc71d4 --- /dev/null +++ b/roms/u-boot/drivers/clk/exynos/clk-pll.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Exynos PLL helper functions for clock drivers. + * Copyright (C) 2016 Samsung Electronics + * Thomas Abraham <thomas.ab@samsung.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <div64.h> + +#define PLL145X_MDIV_SHIFT 16 +#define PLL145X_MDIV_MASK 0x3ff +#define PLL145X_PDIV_SHIFT 8 +#define PLL145X_PDIV_MASK 0x3f +#define PLL145X_SDIV_SHIFT 0 +#define PLL145X_SDIV_MASK 0x7 + +unsigned long pll145x_get_rate(unsigned int *con1, unsigned long fin_freq) +{ + unsigned long pll_con1 = readl(con1); + unsigned long mdiv, sdiv, pdiv; + uint64_t fvco = fin_freq; + + mdiv = (pll_con1 >> PLL145X_MDIV_SHIFT) & PLL145X_MDIV_MASK; + pdiv = (pll_con1 >> PLL145X_PDIV_SHIFT) & PLL145X_PDIV_MASK; + sdiv = (pll_con1 >> PLL145X_SDIV_SHIFT) & PLL145X_SDIV_MASK; + + fvco *= mdiv; + do_div(fvco, (pdiv << sdiv)); + return (unsigned long)fvco; +} diff --git a/roms/u-boot/drivers/clk/exynos/clk-pll.h b/roms/u-boot/drivers/clk/exynos/clk-pll.h new file mode 100644 index 000000000..c79aac442 --- /dev/null +++ b/roms/u-boot/drivers/clk/exynos/clk-pll.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Exynos PLL helper functions for clock drivers. + * Copyright (C) 2016 Samsung Electronics + * Thomas Abraham <thomas.ab@samsung.com> + */ + +unsigned long pll145x_get_rate(unsigned int *con1, unsigned long fin_freq); |