2 * Samsung Exynos7420 clock driver.
3 * Copyright (C) 2016 Samsung Electronics
4 * Thomas Abraham <thomas.ab@samsung.com>
6 * SPDX-License-Identifier: GPL-2.0+
12 #include <clk-uclass.h>
14 #include <dt-bindings/clock/exynos7420-clk.h>
17 DECLARE_GLOBAL_DATA_PTR
;
19 #define DIVIDER(reg, shift, mask) \
20 (((readl(reg) >> shift) & mask) + 1)
22 /* CMU TOPC block device structure */
23 struct exynos7420_clk_cmu_topc
{
24 unsigned int rsvd1
[68];
25 unsigned int bus0_pll_con
[2];
26 unsigned int rsvd2
[2];
27 unsigned int bus1_pll_con
[2];
28 unsigned int rsvd3
[54];
29 unsigned int mux_sel
[6];
30 unsigned int rsvd4
[250];
34 /* CMU TOP0 block device structure */
35 struct exynos7420_clk_cmu_top0
{
36 unsigned int rsvd0
[128];
37 unsigned int mux_sel
[7];
38 unsigned int rsvd1
[261];
39 unsigned int div_peric
[5];
43 * struct exynos7420_clk_topc_priv - private data for CMU topc clock driver.
45 * @topc: base address of the memory mapped CMU TOPC controller.
46 * @fin_freq: frequency of the Oscillator clock.
47 * @sclk_bus0_pll_a: frequency of sclk_bus0_pll_a clock.
48 * @sclk_bus1_pll_a: frequency of sclk_bus1_pll_a clock.
50 struct exynos7420_clk_topc_priv
{
51 struct exynos7420_clk_cmu_topc
*topc
;
52 unsigned long fin_freq
;
53 unsigned long sclk_bus0_pll_a
;
54 unsigned long sclk_bus1_pll_a
;
58 * struct exynos7420_clk_top0_priv - private data for CMU top0 clock driver.
60 * @top0: base address of the memory mapped CMU TOP0 controller.
61 * @mout_top0_bus0_pll_half: frequency of mout_top0_bus0_pll_half clock
62 * @sclk_uart2: frequency of sclk_uart2 clock.
64 struct exynos7420_clk_top0_priv
{
65 struct exynos7420_clk_cmu_top0
*top0
;
66 unsigned long mout_top0_bus0_pll_half
;
67 unsigned long sclk_uart2
;
70 static ulong
exynos7420_topc_get_rate(struct clk
*clk
)
72 struct exynos7420_clk_topc_priv
*priv
= dev_get_priv(clk
->dev
);
75 case DOUT_SCLK_BUS0_PLL
:
78 return priv
->sclk_bus0_pll_a
;
79 case DOUT_SCLK_BUS1_PLL
:
82 return priv
->sclk_bus1_pll_a
;
88 static struct clk_ops exynos7420_clk_topc_ops
= {
89 .get_rate
= exynos7420_topc_get_rate
,
92 static int exynos7420_clk_topc_probe(struct udevice
*dev
)
94 struct exynos7420_clk_topc_priv
*priv
= dev_get_priv(dev
);
95 struct exynos7420_clk_cmu_topc
*topc
;
101 base
= devfdt_get_addr(dev
);
102 if (base
== FDT_ADDR_T_NONE
)
105 topc
= (struct exynos7420_clk_cmu_topc
*)base
;
108 ret
= clk_get_by_index(dev
, 0, &in_clk
);
110 priv
->fin_freq
= clk_get_rate(&in_clk
);
112 rate
= pll145x_get_rate(&topc
->bus0_pll_con
[0], priv
->fin_freq
);
113 if (readl(&topc
->mux_sel
[1]) & (1 << 16))
115 rate
/= DIVIDER(&topc
->div
[3], 0, 0xf);
116 priv
->sclk_bus0_pll_a
= rate
;
118 rate
= pll145x_get_rate(&topc
->bus1_pll_con
[0], priv
->fin_freq
) /
119 DIVIDER(&topc
->div
[3], 8, 0xf);
120 priv
->sclk_bus1_pll_a
= rate
;
125 static ulong
exynos7420_top0_get_rate(struct clk
*clk
)
127 struct exynos7420_clk_top0_priv
*priv
= dev_get_priv(clk
->dev
);
128 struct exynos7420_clk_cmu_top0
*top0
= priv
->top0
;
132 return priv
->mout_top0_bus0_pll_half
/
133 DIVIDER(&top0
->div_peric
[3], 8, 0xf);
139 static struct clk_ops exynos7420_clk_top0_ops
= {
140 .get_rate
= exynos7420_top0_get_rate
,
143 static int exynos7420_clk_top0_probe(struct udevice
*dev
)
145 struct exynos7420_clk_top0_priv
*priv
;
146 struct exynos7420_clk_cmu_top0
*top0
;
151 priv
= dev_get_priv(dev
);
155 base
= devfdt_get_addr(dev
);
156 if (base
== FDT_ADDR_T_NONE
)
159 top0
= (struct exynos7420_clk_cmu_top0
*)base
;
162 ret
= clk_get_by_index(dev
, 1, &in_clk
);
164 priv
->mout_top0_bus0_pll_half
=
165 clk_get_rate(&in_clk
);
166 if (readl(&top0
->mux_sel
[1]) & (1 << 16))
167 priv
->mout_top0_bus0_pll_half
>>= 1;
173 static ulong
exynos7420_peric1_get_rate(struct clk
*clk
)
177 unsigned long freq
= 0;
181 ret
= clk_get_by_index(clk
->dev
, 3, &in_clk
);
184 freq
= clk_get_rate(&in_clk
);
191 static struct clk_ops exynos7420_clk_peric1_ops
= {
192 .get_rate
= exynos7420_peric1_get_rate
,
195 static const struct udevice_id exynos7420_clk_topc_compat
[] = {
196 { .compatible
= "samsung,exynos7-clock-topc" },
200 U_BOOT_DRIVER(exynos7420_clk_topc
) = {
201 .name
= "exynos7420-clock-topc",
203 .of_match
= exynos7420_clk_topc_compat
,
204 .probe
= exynos7420_clk_topc_probe
,
205 .priv_auto_alloc_size
= sizeof(struct exynos7420_clk_topc_priv
),
206 .ops
= &exynos7420_clk_topc_ops
,
207 .flags
= DM_FLAG_PRE_RELOC
,
210 static const struct udevice_id exynos7420_clk_top0_compat
[] = {
211 { .compatible
= "samsung,exynos7-clock-top0" },
215 U_BOOT_DRIVER(exynos7420_clk_top0
) = {
216 .name
= "exynos7420-clock-top0",
218 .of_match
= exynos7420_clk_top0_compat
,
219 .probe
= exynos7420_clk_top0_probe
,
220 .priv_auto_alloc_size
= sizeof(struct exynos7420_clk_top0_priv
),
221 .ops
= &exynos7420_clk_top0_ops
,
222 .flags
= DM_FLAG_PRE_RELOC
,
225 static const struct udevice_id exynos7420_clk_peric1_compat
[] = {
226 { .compatible
= "samsung,exynos7-clock-peric1" },
230 U_BOOT_DRIVER(exynos7420_clk_peric1
) = {
231 .name
= "exynos7420-clock-peric1",
233 .of_match
= exynos7420_clk_peric1_compat
,
234 .ops
= &exynos7420_clk_peric1_ops
,
235 .flags
= DM_FLAG_PRE_RELOC
,