1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2015-2020, NVIDIA CORPORATION. All rights reserved.
6 #include <linux/bitfield.h>
8 #include <linux/clk-provider.h>
9 #include <linux/clk/tegra.h>
10 #include <linux/device.h>
11 #include <linux/module.h>
13 #include <linux/slab.h>
17 #define CLK_SOURCE_EMC 0x19c
18 #define CLK_SOURCE_EMC_2X_CLK_SRC GENMASK(31, 29)
19 #define CLK_SOURCE_EMC_MC_EMC_SAME_FREQ BIT(16)
20 #define CLK_SOURCE_EMC_2X_CLK_DIVISOR GENMASK(7, 0)
22 #define CLK_SRC_PLLM 0
23 #define CLK_SRC_PLLC 1
24 #define CLK_SRC_PLLP 2
25 #define CLK_SRC_CLK_M 3
26 #define CLK_SRC_PLLM_UD 4
27 #define CLK_SRC_PLLMB_UD 5
28 #define CLK_SRC_PLLMB 6
29 #define CLK_SRC_PLLP_UD 7
31 struct tegra210_clk_emc
{
35 struct tegra210_clk_emc_provider
*provider
;
37 struct clk
*parents
[8];
40 static inline struct tegra210_clk_emc
*
41 to_tegra210_clk_emc(struct clk_hw
*hw
)
43 return container_of(hw
, struct tegra210_clk_emc
, hw
);
46 static const char *tegra210_clk_emc_parents
[] = {
47 "pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_mb_ud",
51 static u8
tegra210_clk_emc_get_parent(struct clk_hw
*hw
)
53 struct tegra210_clk_emc
*emc
= to_tegra210_clk_emc(hw
);
57 value
= readl_relaxed(emc
->regs
+ CLK_SOURCE_EMC
);
58 src
= FIELD_GET(CLK_SOURCE_EMC_2X_CLK_SRC
, value
);
63 static unsigned long tegra210_clk_emc_recalc_rate(struct clk_hw
*hw
,
64 unsigned long parent_rate
)
66 struct tegra210_clk_emc
*emc
= to_tegra210_clk_emc(hw
);
70 * CCF assumes that neither the parent nor its rate will change during
71 * ->set_rate(), so the parent rate passed in here was cached from the
72 * parent before the ->set_rate() call.
74 * This can lead to wrong results being reported for the EMC clock if
75 * the parent and/or parent rate have changed as part of the EMC rate
76 * change sequence. Fix this by overriding the parent clock with what
77 * we know to be the correct value after the rate change.
79 parent_rate
= clk_hw_get_rate(clk_hw_get_parent(hw
));
81 value
= readl_relaxed(emc
->regs
+ CLK_SOURCE_EMC
);
83 div
= FIELD_GET(CLK_SOURCE_EMC_2X_CLK_DIVISOR
, value
);
86 return DIV_ROUND_UP(parent_rate
* 2, div
);
89 static long tegra210_clk_emc_round_rate(struct clk_hw
*hw
, unsigned long rate
,
92 struct tegra210_clk_emc
*emc
= to_tegra210_clk_emc(hw
);
93 struct tegra210_clk_emc_provider
*provider
= emc
->provider
;
96 if (!provider
|| !provider
->configs
|| provider
->num_configs
== 0)
97 return clk_hw_get_rate(hw
);
99 for (i
= 0; i
< provider
->num_configs
; i
++) {
100 if (provider
->configs
[i
].rate
>= rate
)
101 return provider
->configs
[i
].rate
;
104 return provider
->configs
[i
- 1].rate
;
107 static struct clk
*tegra210_clk_emc_find_parent(struct tegra210_clk_emc
*emc
,
110 struct clk_hw
*parent
= clk_hw_get_parent_by_index(&emc
->hw
, index
);
111 const char *name
= clk_hw_get_name(parent
);
113 /* XXX implement cache? */
115 return __clk_lookup(name
);
118 static int tegra210_clk_emc_set_rate(struct clk_hw
*hw
, unsigned long rate
,
119 unsigned long parent_rate
)
121 struct tegra210_clk_emc
*emc
= to_tegra210_clk_emc(hw
);
122 struct tegra210_clk_emc_provider
*provider
= emc
->provider
;
123 struct tegra210_clk_emc_config
*config
;
124 struct device
*dev
= provider
->dev
;
125 struct clk_hw
*old
, *new, *parent
;
126 u8 old_idx
, new_idx
, index
;
131 if (!provider
->configs
|| provider
->num_configs
== 0)
134 for (i
= 0; i
< provider
->num_configs
; i
++) {
135 if (provider
->configs
[i
].rate
>= rate
) {
136 config
= &provider
->configs
[i
];
141 if (i
== provider
->num_configs
)
142 config
= &provider
->configs
[i
- 1];
144 old_idx
= tegra210_clk_emc_get_parent(hw
);
145 new_idx
= FIELD_GET(CLK_SOURCE_EMC_2X_CLK_SRC
, config
->value
);
147 old
= clk_hw_get_parent_by_index(hw
, old_idx
);
148 new = clk_hw_get_parent_by_index(hw
, new_idx
);
150 /* if the rate has changed... */
151 if (config
->parent_rate
!= clk_hw_get_rate(old
)) {
152 /* ... but the clock source remains the same ... */
153 if (new_idx
== old_idx
) {
154 /* ... switch to the alternative clock source. */
157 new_idx
= CLK_SRC_PLLMB
;
160 case CLK_SRC_PLLM_UD
:
161 new_idx
= CLK_SRC_PLLMB_UD
;
164 case CLK_SRC_PLLMB_UD
:
165 new_idx
= CLK_SRC_PLLM_UD
;
169 new_idx
= CLK_SRC_PLLM
;
174 * This should never happen because we can't deal with
177 if (WARN_ON(new_idx
== old_idx
))
180 new = clk_hw_get_parent_by_index(hw
, new_idx
);
190 clk
= tegra210_clk_emc_find_parent(emc
, index
);
193 dev_err(dev
, "failed to get parent clock for index %u: %d\n",
198 /* set the new parent clock to the required rate */
199 if (clk_get_rate(clk
) != config
->parent_rate
) {
200 err
= clk_set_rate(clk
, config
->parent_rate
);
202 dev_err(dev
, "failed to set rate %lu Hz for %pC: %d\n",
203 config
->parent_rate
, clk
, err
);
208 /* enable the new parent clock */
210 err
= clk_prepare_enable(clk
);
212 dev_err(dev
, "failed to enable parent clock %pC: %d\n",
218 /* update the EMC source configuration to reflect the new parent */
219 config
->value
&= ~CLK_SOURCE_EMC_2X_CLK_SRC
;
220 config
->value
|= FIELD_PREP(CLK_SOURCE_EMC_2X_CLK_SRC
, index
);
223 * Finally, switch the EMC programming with both old and new parent
226 err
= provider
->set_rate(dev
, config
);
228 dev_err(dev
, "failed to set EMC rate to %lu Hz: %d\n", rate
,
232 * If we're unable to switch to the new EMC frequency, we no
233 * longer need the new parent to be enabled.
236 clk_disable_unprepare(clk
);
241 /* reparent to new parent clock and disable the old parent clock */
243 clk
= tegra210_clk_emc_find_parent(emc
, old_idx
);
247 "failed to get parent clock for index %u: %d\n",
252 clk_hw_reparent(hw
, parent
);
253 clk_disable_unprepare(clk
);
259 static const struct clk_ops tegra210_clk_emc_ops
= {
260 .get_parent
= tegra210_clk_emc_get_parent
,
261 .recalc_rate
= tegra210_clk_emc_recalc_rate
,
262 .round_rate
= tegra210_clk_emc_round_rate
,
263 .set_rate
= tegra210_clk_emc_set_rate
,
266 struct clk
*tegra210_clk_register_emc(struct device_node
*np
,
269 struct tegra210_clk_emc
*emc
;
270 struct clk_init_data init
;
273 emc
= kzalloc(sizeof(*emc
), GFP_KERNEL
);
275 return ERR_PTR(-ENOMEM
);
280 init
.ops
= &tegra210_clk_emc_ops
;
281 init
.flags
= CLK_IS_CRITICAL
| CLK_GET_RATE_NOCACHE
;
282 init
.parent_names
= tegra210_clk_emc_parents
;
283 init
.num_parents
= ARRAY_SIZE(tegra210_clk_emc_parents
);
284 emc
->hw
.init
= &init
;
286 clk
= clk_register(NULL
, &emc
->hw
);
295 int tegra210_clk_emc_attach(struct clk
*clk
,
296 struct tegra210_clk_emc_provider
*provider
)
298 struct clk_hw
*hw
= __clk_get_hw(clk
);
299 struct tegra210_clk_emc
*emc
= to_tegra210_clk_emc(hw
);
300 struct device
*dev
= provider
->dev
;
304 if (!try_module_get(provider
->owner
))
307 for (i
= 0; i
< provider
->num_configs
; i
++) {
308 struct tegra210_clk_emc_config
*config
= &provider
->configs
[i
];
309 struct clk_hw
*parent
;
313 div
= FIELD_GET(CLK_SOURCE_EMC_2X_CLK_DIVISOR
, config
->value
);
314 src
= FIELD_GET(CLK_SOURCE_EMC_2X_CLK_SRC
, config
->value
);
316 /* do basic sanity checking on the EMC timings */
318 dev_err(dev
, "invalid odd divider %u for rate %lu Hz\n",
324 same_freq
= config
->value
& CLK_SOURCE_EMC_MC_EMC_SAME_FREQ
;
326 if (same_freq
!= config
->same_freq
) {
328 "ambiguous EMC to MC ratio for rate %lu Hz\n",
334 parent
= clk_hw_get_parent_by_index(hw
, src
);
335 config
->parent
= src
;
337 if (src
== CLK_SRC_PLLM
|| src
== CLK_SRC_PLLM_UD
) {
338 config
->parent_rate
= config
->rate
* (1 + div
/ 2);
340 unsigned long rate
= config
->rate
* (1 + div
/ 2);
342 config
->parent_rate
= clk_hw_get_rate(parent
);
344 if (config
->parent_rate
!= rate
) {
346 "rate %lu Hz does not match input\n",
354 emc
->provider
= provider
;
359 module_put(provider
->owner
);
362 EXPORT_SYMBOL_GPL(tegra210_clk_emc_attach
);
364 void tegra210_clk_emc_detach(struct clk
*clk
)
366 struct tegra210_clk_emc
*emc
= to_tegra210_clk_emc(__clk_get_hw(clk
));
368 module_put(emc
->provider
->owner
);
369 emc
->provider
= NULL
;
371 EXPORT_SYMBOL_GPL(tegra210_clk_emc_detach
);