1 // SPDX-License-Identifier: GPL-2.0+
3 * Samsung Exynos7420 clock driver.
4 * Copyright (C) 2016 Samsung Electronics
5 * Thomas Abraham <thomas.ab@samsung.com>
11 #include <clk-uclass.h>
13 #include <dt-bindings/clock/exynos7420-clk.h>
16 #define DIVIDER(reg, shift, mask) \
17 (((readl(reg) >> shift) & mask) + 1)
19 /* CMU TOPC block device structure */
20 struct exynos7420_clk_cmu_topc {
21 unsigned int rsvd1[68];
22 unsigned int bus0_pll_con[2];
23 unsigned int rsvd2[2];
24 unsigned int bus1_pll_con[2];
25 unsigned int rsvd3[54];
26 unsigned int mux_sel[6];
27 unsigned int rsvd4[250];
31 /* CMU TOP0 block device structure */
32 struct exynos7420_clk_cmu_top0 {
33 unsigned int rsvd0[128];
34 unsigned int mux_sel[7];
35 unsigned int rsvd1[261];
36 unsigned int div_peric[5];
40 * struct exynos7420_clk_topc_priv - private data for CMU topc clock driver.
42 * @topc: base address of the memory mapped CMU TOPC controller.
43 * @fin_freq: frequency of the Oscillator clock.
44 * @sclk_bus0_pll_a: frequency of sclk_bus0_pll_a clock.
45 * @sclk_bus1_pll_a: frequency of sclk_bus1_pll_a clock.
47 struct exynos7420_clk_topc_priv {
48 struct exynos7420_clk_cmu_topc *topc;
49 unsigned long fin_freq;
50 unsigned long sclk_bus0_pll_a;
51 unsigned long sclk_bus1_pll_a;
55 * struct exynos7420_clk_top0_priv - private data for CMU top0 clock driver.
57 * @top0: base address of the memory mapped CMU TOP0 controller.
58 * @mout_top0_bus0_pll_half: frequency of mout_top0_bus0_pll_half clock
59 * @sclk_uart2: frequency of sclk_uart2 clock.
61 struct exynos7420_clk_top0_priv {
62 struct exynos7420_clk_cmu_top0 *top0;
63 unsigned long mout_top0_bus0_pll_half;
64 unsigned long sclk_uart2;
67 static ulong exynos7420_topc_get_rate(struct clk *clk)
69 struct exynos7420_clk_topc_priv *priv = dev_get_priv(clk->dev);
72 case DOUT_SCLK_BUS0_PLL:
75 return priv->sclk_bus0_pll_a;
76 case DOUT_SCLK_BUS1_PLL:
79 return priv->sclk_bus1_pll_a;
85 static struct clk_ops exynos7420_clk_topc_ops = {
86 .get_rate = exynos7420_topc_get_rate,
89 static int exynos7420_clk_topc_probe(struct udevice *dev)
91 struct exynos7420_clk_topc_priv *priv = dev_get_priv(dev);
92 struct exynos7420_clk_cmu_topc *topc;
98 base = devfdt_get_addr(dev);
99 if (base == FDT_ADDR_T_NONE)
102 topc = (struct exynos7420_clk_cmu_topc *)base;
105 ret = clk_get_by_index(dev, 0, &in_clk);
107 priv->fin_freq = clk_get_rate(&in_clk);
109 rate = pll145x_get_rate(&topc->bus0_pll_con[0], priv->fin_freq);
110 if (readl(&topc->mux_sel[1]) & (1 << 16))
112 rate /= DIVIDER(&topc->div[3], 0, 0xf);
113 priv->sclk_bus0_pll_a = rate;
115 rate = pll145x_get_rate(&topc->bus1_pll_con[0], priv->fin_freq) /
116 DIVIDER(&topc->div[3], 8, 0xf);
117 priv->sclk_bus1_pll_a = rate;
122 static ulong exynos7420_top0_get_rate(struct clk *clk)
124 struct exynos7420_clk_top0_priv *priv = dev_get_priv(clk->dev);
125 struct exynos7420_clk_cmu_top0 *top0 = priv->top0;
129 return priv->mout_top0_bus0_pll_half /
130 DIVIDER(&top0->div_peric[3], 8, 0xf);
136 static struct clk_ops exynos7420_clk_top0_ops = {
137 .get_rate = exynos7420_top0_get_rate,
140 static int exynos7420_clk_top0_probe(struct udevice *dev)
142 struct exynos7420_clk_top0_priv *priv;
143 struct exynos7420_clk_cmu_top0 *top0;
148 priv = dev_get_priv(dev);
152 base = devfdt_get_addr(dev);
153 if (base == FDT_ADDR_T_NONE)
156 top0 = (struct exynos7420_clk_cmu_top0 *)base;
159 ret = clk_get_by_index(dev, 1, &in_clk);
161 priv->mout_top0_bus0_pll_half =
162 clk_get_rate(&in_clk);
163 if (readl(&top0->mux_sel[1]) & (1 << 16))
164 priv->mout_top0_bus0_pll_half >>= 1;
170 static ulong exynos7420_peric1_get_rate(struct clk *clk)
174 unsigned long freq = 0;
178 ret = clk_get_by_index(clk->dev, 3, &in_clk);
181 freq = clk_get_rate(&in_clk);
188 static struct clk_ops exynos7420_clk_peric1_ops = {
189 .get_rate = exynos7420_peric1_get_rate,
192 static const struct udevice_id exynos7420_clk_topc_compat[] = {
193 { .compatible = "samsung,exynos7-clock-topc" },
197 U_BOOT_DRIVER(exynos7420_clk_topc) = {
198 .name = "exynos7420-clock-topc",
200 .of_match = exynos7420_clk_topc_compat,
201 .probe = exynos7420_clk_topc_probe,
202 .priv_auto_alloc_size = sizeof(struct exynos7420_clk_topc_priv),
203 .ops = &exynos7420_clk_topc_ops,
204 .flags = DM_FLAG_PRE_RELOC,
207 static const struct udevice_id exynos7420_clk_top0_compat[] = {
208 { .compatible = "samsung,exynos7-clock-top0" },
212 U_BOOT_DRIVER(exynos7420_clk_top0) = {
213 .name = "exynos7420-clock-top0",
215 .of_match = exynos7420_clk_top0_compat,
216 .probe = exynos7420_clk_top0_probe,
217 .priv_auto_alloc_size = sizeof(struct exynos7420_clk_top0_priv),
218 .ops = &exynos7420_clk_top0_ops,
219 .flags = DM_FLAG_PRE_RELOC,
222 static const struct udevice_id exynos7420_clk_peric1_compat[] = {
223 { .compatible = "samsung,exynos7-clock-peric1" },
227 U_BOOT_DRIVER(exynos7420_clk_peric1) = {
228 .name = "exynos7420-clock-peric1",
230 .of_match = exynos7420_clk_peric1_compat,
231 .ops = &exynos7420_clk_peric1_ops,
232 .flags = DM_FLAG_PRE_RELOC,