]> git.ipfire.org Git - thirdparty/u-boot.git/blame - drivers/clk/exynos/clk-exynos7420.c
Revert "Merge patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet""
[thirdparty/u-boot.git] / drivers / clk / exynos / clk-exynos7420.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
166097e8
TA
2/*
3 * Samsung Exynos7420 clock driver.
4 * Copyright (C) 2016 Samsung Electronics
5 * Thomas Abraham <thomas.ab@samsung.com>
166097e8
TA
6 */
7
d678a59d 8#include <common.h>
166097e8
TA
9#include <dm.h>
10#include <errno.h>
135aa950 11#include <clk-uclass.h>
166097e8 12#include <asm/io.h>
0caae9fd 13#include <div64.h>
166097e8 14#include <dt-bindings/clock/exynos7420-clk.h>
0caae9fd
SP
15
16#define PLL145X_MDIV_SHIFT 16
17#define PLL145X_MDIV_MASK 0x3ff
18#define PLL145X_PDIV_SHIFT 8
19#define PLL145X_PDIV_MASK 0x3f
20#define PLL145X_SDIV_SHIFT 0
21#define PLL145X_SDIV_MASK 0x7
166097e8 22
166097e8
TA
23#define DIVIDER(reg, shift, mask) \
24 (((readl(reg) >> shift) & mask) + 1)
25
26/* CMU TOPC block device structure */
27struct exynos7420_clk_cmu_topc {
28 unsigned int rsvd1[68];
29 unsigned int bus0_pll_con[2];
30 unsigned int rsvd2[2];
31 unsigned int bus1_pll_con[2];
32 unsigned int rsvd3[54];
33 unsigned int mux_sel[6];
34 unsigned int rsvd4[250];
35 unsigned int div[4];
36};
37
38/* CMU TOP0 block device structure */
39struct exynos7420_clk_cmu_top0 {
40 unsigned int rsvd0[128];
41 unsigned int mux_sel[7];
42 unsigned int rsvd1[261];
43 unsigned int div_peric[5];
44};
45
46/**
47 * struct exynos7420_clk_topc_priv - private data for CMU topc clock driver.
48 *
49 * @topc: base address of the memory mapped CMU TOPC controller.
50 * @fin_freq: frequency of the Oscillator clock.
51 * @sclk_bus0_pll_a: frequency of sclk_bus0_pll_a clock.
52 * @sclk_bus1_pll_a: frequency of sclk_bus1_pll_a clock.
53 */
54struct exynos7420_clk_topc_priv {
55 struct exynos7420_clk_cmu_topc *topc;
56 unsigned long fin_freq;
57 unsigned long sclk_bus0_pll_a;
58 unsigned long sclk_bus1_pll_a;
59};
60
61/**
62 * struct exynos7420_clk_top0_priv - private data for CMU top0 clock driver.
63 *
64 * @top0: base address of the memory mapped CMU TOP0 controller.
65 * @mout_top0_bus0_pll_half: frequency of mout_top0_bus0_pll_half clock
66 * @sclk_uart2: frequency of sclk_uart2 clock.
67 */
68struct exynos7420_clk_top0_priv {
69 struct exynos7420_clk_cmu_top0 *top0;
70 unsigned long mout_top0_bus0_pll_half;
71 unsigned long sclk_uart2;
72};
73
0caae9fd
SP
74static unsigned long pll145x_get_rate(unsigned int *con1,
75 unsigned long fin_freq)
76{
77 unsigned long pll_con1 = readl(con1);
78 unsigned long mdiv, sdiv, pdiv;
79 u64 fvco = fin_freq;
80
81 mdiv = (pll_con1 >> PLL145X_MDIV_SHIFT) & PLL145X_MDIV_MASK;
82 pdiv = (pll_con1 >> PLL145X_PDIV_SHIFT) & PLL145X_PDIV_MASK;
83 sdiv = (pll_con1 >> PLL145X_SDIV_SHIFT) & PLL145X_SDIV_MASK;
84
85 fvco *= mdiv;
86 do_div(fvco, (pdiv << sdiv));
87 return (unsigned long)fvco;
88}
89
135aa950 90static ulong exynos7420_topc_get_rate(struct clk *clk)
166097e8 91{
135aa950 92 struct exynos7420_clk_topc_priv *priv = dev_get_priv(clk->dev);
166097e8 93
135aa950 94 switch (clk->id) {
166097e8
TA
95 case DOUT_SCLK_BUS0_PLL:
96 case SCLK_BUS0_PLL_A:
97 case SCLK_BUS0_PLL_B:
98 return priv->sclk_bus0_pll_a;
99 case DOUT_SCLK_BUS1_PLL:
100 case SCLK_BUS1_PLL_A:
101 case SCLK_BUS1_PLL_B:
102 return priv->sclk_bus1_pll_a;
103 default:
104 return 0;
105 }
106}
107
108static struct clk_ops exynos7420_clk_topc_ops = {
135aa950 109 .get_rate = exynos7420_topc_get_rate,
166097e8
TA
110};
111
112static int exynos7420_clk_topc_probe(struct udevice *dev)
113{
114 struct exynos7420_clk_topc_priv *priv = dev_get_priv(dev);
115 struct exynos7420_clk_cmu_topc *topc;
135aa950 116 struct clk in_clk;
166097e8
TA
117 unsigned long rate;
118 fdt_addr_t base;
119 int ret;
120
2548493a 121 base = dev_read_addr(dev);
166097e8
TA
122 if (base == FDT_ADDR_T_NONE)
123 return -EINVAL;
124
125 topc = (struct exynos7420_clk_cmu_topc *)base;
126 priv->topc = topc;
127
135aa950 128 ret = clk_get_by_index(dev, 0, &in_clk);
166097e8 129 if (ret >= 0)
135aa950 130 priv->fin_freq = clk_get_rate(&in_clk);
166097e8
TA
131
132 rate = pll145x_get_rate(&topc->bus0_pll_con[0], priv->fin_freq);
133 if (readl(&topc->mux_sel[1]) & (1 << 16))
134 rate >>= 1;
135 rate /= DIVIDER(&topc->div[3], 0, 0xf);
136 priv->sclk_bus0_pll_a = rate;
137
138 rate = pll145x_get_rate(&topc->bus1_pll_con[0], priv->fin_freq) /
139 DIVIDER(&topc->div[3], 8, 0xf);
140 priv->sclk_bus1_pll_a = rate;
141
142 return 0;
143}
144
135aa950 145static ulong exynos7420_top0_get_rate(struct clk *clk)
166097e8 146{
135aa950 147 struct exynos7420_clk_top0_priv *priv = dev_get_priv(clk->dev);
166097e8
TA
148 struct exynos7420_clk_cmu_top0 *top0 = priv->top0;
149
135aa950 150 switch (clk->id) {
166097e8
TA
151 case CLK_SCLK_UART2:
152 return priv->mout_top0_bus0_pll_half /
153 DIVIDER(&top0->div_peric[3], 8, 0xf);
154 default:
155 return 0;
156 }
157}
158
159static struct clk_ops exynos7420_clk_top0_ops = {
135aa950 160 .get_rate = exynos7420_top0_get_rate,
166097e8
TA
161};
162
163static int exynos7420_clk_top0_probe(struct udevice *dev)
164{
165 struct exynos7420_clk_top0_priv *priv;
166 struct exynos7420_clk_cmu_top0 *top0;
135aa950 167 struct clk in_clk;
166097e8
TA
168 fdt_addr_t base;
169 int ret;
170
171 priv = dev_get_priv(dev);
172 if (!priv)
173 return -EINVAL;
174
2548493a 175 base = dev_read_addr(dev);
166097e8
TA
176 if (base == FDT_ADDR_T_NONE)
177 return -EINVAL;
178
179 top0 = (struct exynos7420_clk_cmu_top0 *)base;
180 priv->top0 = top0;
181
135aa950 182 ret = clk_get_by_index(dev, 1, &in_clk);
166097e8
TA
183 if (ret >= 0) {
184 priv->mout_top0_bus0_pll_half =
135aa950 185 clk_get_rate(&in_clk);
166097e8
TA
186 if (readl(&top0->mux_sel[1]) & (1 << 16))
187 priv->mout_top0_bus0_pll_half >>= 1;
188 }
189
190 return 0;
191}
192
135aa950 193static ulong exynos7420_peric1_get_rate(struct clk *clk)
166097e8 194{
135aa950 195 struct clk in_clk;
166097e8
TA
196 unsigned int ret;
197 unsigned long freq = 0;
198
135aa950 199 switch (clk->id) {
166097e8 200 case SCLK_UART2:
135aa950 201 ret = clk_get_by_index(clk->dev, 3, &in_clk);
166097e8
TA
202 if (ret < 0)
203 return ret;
135aa950 204 freq = clk_get_rate(&in_clk);
166097e8
TA
205 break;
206 }
207
208 return freq;
209}
210
211static struct clk_ops exynos7420_clk_peric1_ops = {
135aa950 212 .get_rate = exynos7420_peric1_get_rate,
166097e8
TA
213};
214
215static const struct udevice_id exynos7420_clk_topc_compat[] = {
216 { .compatible = "samsung,exynos7-clock-topc" },
217 { }
218};
219
220U_BOOT_DRIVER(exynos7420_clk_topc) = {
221 .name = "exynos7420-clock-topc",
222 .id = UCLASS_CLK,
223 .of_match = exynos7420_clk_topc_compat,
224 .probe = exynos7420_clk_topc_probe,
41575d8e 225 .priv_auto = sizeof(struct exynos7420_clk_topc_priv),
166097e8 226 .ops = &exynos7420_clk_topc_ops,
166097e8
TA
227};
228
229static const struct udevice_id exynos7420_clk_top0_compat[] = {
230 { .compatible = "samsung,exynos7-clock-top0" },
231 { }
232};
233
234U_BOOT_DRIVER(exynos7420_clk_top0) = {
235 .name = "exynos7420-clock-top0",
236 .id = UCLASS_CLK,
237 .of_match = exynos7420_clk_top0_compat,
238 .probe = exynos7420_clk_top0_probe,
41575d8e 239 .priv_auto = sizeof(struct exynos7420_clk_top0_priv),
166097e8 240 .ops = &exynos7420_clk_top0_ops,
166097e8
TA
241};
242
243static const struct udevice_id exynos7420_clk_peric1_compat[] = {
244 { .compatible = "samsung,exynos7-clock-peric1" },
245 { }
246};
247
248U_BOOT_DRIVER(exynos7420_clk_peric1) = {
249 .name = "exynos7420-clock-peric1",
250 .id = UCLASS_CLK,
251 .of_match = exynos7420_clk_peric1_compat,
252 .ops = &exynos7420_clk_peric1_ops,
166097e8 253};