aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Turquette <mturquette@baylibre.com>2015-06-20 16:29:48 -0400
committerMichael Turquette <mturquette@baylibre.com>2015-06-20 16:29:48 -0400
commit2cd7b0432888ef2e1f8b54c1c6f8751e1e0e9b5e (patch)
tree8ecab6ac6ef54b4ccc7b93a6a079e72a6ff7d640
parent85e88fab134d8896cf4d8be0aac10cc54018ee63 (diff)
parent36b7be6d3ea8f434f1e0723f3fb0e85c3e00ebc2 (diff)
Merge tag 'tegra-for-4.2-clk' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into clk-next
clk: tegra: Changes for v4.2-rc1 This contains the EMC clock driver that's been exhaustively reviewed and tested. It also includes a change to the clock core that allows a clock provider to perform low-level reparenting of clocks. This is required by the EMC clock driver because the reparenting needs to be done at a very specific point in time during the EMC frequency switch.
-rw-r--r--Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt44
-rw-r--r--Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt2
-rw-r--r--drivers/clk/Kconfig1
-rw-r--r--drivers/clk/clk.c8
-rw-r--r--drivers/clk/tegra/Kconfig3
-rw-r--r--drivers/clk/tegra/Makefile1
-rw-r--r--drivers/clk/tegra/clk-emc.c538
-rw-r--r--drivers/clk/tegra/clk-tegra124.c19
-rw-r--r--drivers/clk/tegra/clk-tegra30.c2
-rw-r--r--drivers/clk/tegra/clk.h12
-rw-r--r--drivers/soc/tegra/fuse/tegra-apbmisc.c21
-rw-r--r--include/linux/clk-provider.h1
-rw-r--r--include/soc/tegra/fuse.h1
13 files changed, 637 insertions, 16 deletions
diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt
index c6620bc96703..7f02fb4ca4ad 100644
--- a/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt
+++ b/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt
@@ -20,15 +20,38 @@ Required properties :
20- #reset-cells : Should be 1. 20- #reset-cells : Should be 1.
21 In clock consumers, this cell represents the bit number in the CAR's 21 In clock consumers, this cell represents the bit number in the CAR's
22 array of CLK_RST_CONTROLLER_RST_DEVICES_* registers. 22 array of CLK_RST_CONTROLLER_RST_DEVICES_* registers.
23- nvidia,external-memory-controller : phandle of the EMC driver.
24
25The node should contain a "emc-timings" subnode for each supported RAM type (see
26field RAM_CODE in register PMC_STRAPPING_OPT_A).
27
28Required properties for "emc-timings" nodes :
29- nvidia,ram-code : Should contain the value of RAM_CODE this timing set
30 is used for.
31
32Each "emc-timings" node should contain a "timing" subnode for every supported
33EMC clock rate.
34
35Required properties for "timing" nodes :
36- clock-frequency : Should contain the memory clock rate to which this timing
37relates.
38- nvidia,parent-clock-frequency : Should contain the rate at which the current
39parent of the EMC clock should be running at this timing.
40- clocks : Must contain an entry for each entry in clock-names.
41 See ../clocks/clock-bindings.txt for details.
42- clock-names : Must include the following entries:
43 - emc-parent : the clock that should be the parent of the EMC clock at this
44timing.
23 45
24Example SoC include file: 46Example SoC include file:
25 47
26/ { 48/ {
27 tegra_car: clock { 49 tegra_car: clock@60006000 {
28 compatible = "nvidia,tegra124-car"; 50 compatible = "nvidia,tegra124-car";
29 reg = <0x60006000 0x1000>; 51 reg = <0x60006000 0x1000>;
30 #clock-cells = <1>; 52 #clock-cells = <1>;
31 #reset-cells = <1>; 53 #reset-cells = <1>;
54 nvidia,external-memory-controller = <&emc>;
32 }; 55 };
33 56
34 usb@c5004000 { 57 usb@c5004000 {
@@ -62,4 +85,23 @@ Example board file:
62 &tegra_car { 85 &tegra_car {
63 clocks = <&clk_32k> <&osc>; 86 clocks = <&clk_32k> <&osc>;
64 }; 87 };
88
89 clock@60006000 {
90 emc-timings-3 {
91 nvidia,ram-code = <3>;
92
93 timing-12750000 {
94 clock-frequency = <12750000>;
95 nvidia,parent-clock-frequency = <408000000>;
96 clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
97 clock-names = "emc-parent";
98 };
99 timing-20400000 {
100 clock-frequency = <20400000>;
101 nvidia,parent-clock-frequency = <408000000>;
102 clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
103 clock-names = "emc-parent";
104 };
105 };
106 };
65}; 107};
diff --git a/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt b/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt
index 47b205cc9cc7..4556359c5876 100644
--- a/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt
+++ b/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt
@@ -10,3 +10,5 @@ Required properties:
10 The second entry gives the physical address and length of the 10 The second entry gives the physical address and length of the
11 registers indicating the strapping options. 11 registers indicating the strapping options.
12 12
13Optional properties:
14- nvidia,long-ram-code: If present, the RAM code is long (4 bit). If not, short (2 bit).
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 1dd4f9d8bcb6..42f7120ca9ce 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -176,3 +176,4 @@ endmenu
176source "drivers/clk/mvebu/Kconfig" 176source "drivers/clk/mvebu/Kconfig"
177 177
178source "drivers/clk/samsung/Kconfig" 178source "drivers/clk/samsung/Kconfig"
179source "drivers/clk/tegra/Kconfig"
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 059e5d25c9ba..ddb4b541016f 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1660,6 +1660,14 @@ static void clk_core_reparent(struct clk_core *core,
1660 __clk_recalc_rates(core, POST_RATE_CHANGE); 1660 __clk_recalc_rates(core, POST_RATE_CHANGE);
1661} 1661}
1662 1662
1663void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent)
1664{
1665 if (!hw)
1666 return;
1667
1668 clk_core_reparent(hw->core, !new_parent ? NULL : new_parent->core);
1669}
1670
1663/** 1671/**
1664 * clk_has_parent - check if a clock is a possible parent for another 1672 * clk_has_parent - check if a clock is a possible parent for another
1665 * @clk: clock source 1673 * @clk: clock source
diff --git a/drivers/clk/tegra/Kconfig b/drivers/clk/tegra/Kconfig
new file mode 100644
index 000000000000..1ba30d1e14f2
--- /dev/null
+++ b/drivers/clk/tegra/Kconfig
@@ -0,0 +1,3 @@
1config TEGRA_CLK_EMC
2 def_bool y
3 depends on TEGRA124_EMC
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
index edb8358fa6ce..aec862ba7a17 100644
--- a/drivers/clk/tegra/Makefile
+++ b/drivers/clk/tegra/Makefile
@@ -11,6 +11,7 @@ obj-y += clk-tegra-periph.o
11obj-y += clk-tegra-pmc.o 11obj-y += clk-tegra-pmc.o
12obj-y += clk-tegra-fixed.o 12obj-y += clk-tegra-fixed.o
13obj-y += clk-tegra-super-gen4.o 13obj-y += clk-tegra-super-gen4.o
14obj-$(CONFIG_TEGRA_CLK_EMC) += clk-emc.o
14obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o 15obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o
15obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o 16obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o
16obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o 17obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o
diff --git a/drivers/clk/tegra/clk-emc.c b/drivers/clk/tegra/clk-emc.c
new file mode 100644
index 000000000000..7649685c86bc
--- /dev/null
+++ b/drivers/clk/tegra/clk-emc.c
@@ -0,0 +1,538 @@
1/*
2 * drivers/clk/tegra/clk-emc.c
3 *
4 * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Author:
7 * Mikko Perttunen <mperttunen@nvidia.com>
8 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18
19#include <linux/clk-provider.h>
20#include <linux/clk.h>
21#include <linux/clkdev.h>
22#include <linux/delay.h>
23#include <linux/module.h>
24#include <linux/of_address.h>
25#include <linux/of_platform.h>
26#include <linux/platform_device.h>
27#include <linux/sort.h>
28#include <linux/string.h>
29
30#include <soc/tegra/fuse.h>
31#include <soc/tegra/emc.h>
32
33#include "clk.h"
34
35#define CLK_SOURCE_EMC 0x19c
36
37#define CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR_SHIFT 0
38#define CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR_MASK 0xff
39#define CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR(x) (((x) & CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR_MASK) << \
40 CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR_SHIFT)
41
42#define CLK_SOURCE_EMC_EMC_2X_CLK_SRC_SHIFT 29
43#define CLK_SOURCE_EMC_EMC_2X_CLK_SRC_MASK 0x7
44#define CLK_SOURCE_EMC_EMC_2X_CLK_SRC(x) (((x) & CLK_SOURCE_EMC_EMC_2X_CLK_SRC_MASK) << \
45 CLK_SOURCE_EMC_EMC_2X_CLK_SRC_SHIFT)
46
47static const char * const emc_parent_clk_names[] = {
48 "pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud",
49 "pll_c2", "pll_c3", "pll_c_ud"
50};
51
52/*
53 * List of clock sources for various parents the EMC clock can have.
54 * When we change the timing to a timing with a parent that has the same
55 * clock source as the current parent, we must first change to a backup
56 * timing that has a different clock source.
57 */
58
59#define EMC_SRC_PLL_M 0
60#define EMC_SRC_PLL_C 1
61#define EMC_SRC_PLL_P 2
62#define EMC_SRC_CLK_M 3
63#define EMC_SRC_PLL_C2 4
64#define EMC_SRC_PLL_C3 5
65
66static const char emc_parent_clk_sources[] = {
67 EMC_SRC_PLL_M, EMC_SRC_PLL_C, EMC_SRC_PLL_P, EMC_SRC_CLK_M,
68 EMC_SRC_PLL_M, EMC_SRC_PLL_C2, EMC_SRC_PLL_C3, EMC_SRC_PLL_C
69};
70
71struct emc_timing {
72 unsigned long rate, parent_rate;
73 u8 parent_index;
74 struct clk *parent;
75 u32 ram_code;
76};
77
78struct tegra_clk_emc {
79 struct clk_hw hw;
80 void __iomem *clk_regs;
81 struct clk *prev_parent;
82 bool changing_timing;
83
84 struct device_node *emc_node;
85 struct tegra_emc *emc;
86
87 int num_timings;
88 struct emc_timing *timings;
89 spinlock_t *lock;
90};
91
92/* Common clock framework callback implementations */
93
94static unsigned long emc_recalc_rate(struct clk_hw *hw,
95 unsigned long parent_rate)
96{
97 struct tegra_clk_emc *tegra;
98 u32 val, div;
99
100 tegra = container_of(hw, struct tegra_clk_emc, hw);
101
102 /*
103 * CCF wrongly assumes that the parent won't change during set_rate,
104 * so get the parent rate explicitly.
105 */
106 parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
107
108 val = readl(tegra->clk_regs + CLK_SOURCE_EMC);
109 div = val & CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR_MASK;
110
111 return parent_rate / (div + 2) * 2;
112}
113
114/*
115 * Rounds up unless no higher rate exists, in which case down. This way is
116 * safer since things have EMC rate floors. Also don't touch parent_rate
117 * since we don't want the CCF to play with our parent clocks.
118 */
119static long emc_determine_rate(struct clk_hw *hw, unsigned long rate,
120 unsigned long min_rate,
121 unsigned long max_rate,
122 unsigned long *best_parent_rate,
123 struct clk_hw **best_parent_hw)
124{
125 struct tegra_clk_emc *tegra;
126 u8 ram_code = tegra_read_ram_code();
127 struct emc_timing *timing = NULL;
128 int i;
129
130 tegra = container_of(hw, struct tegra_clk_emc, hw);
131
132 for (i = 0; i < tegra->num_timings; i++) {
133 if (tegra->timings[i].ram_code != ram_code)
134 continue;
135
136 timing = tegra->timings + i;
137
138 if (timing->rate > max_rate) {
139 i = min(i, 1);
140 return tegra->timings[i - 1].rate;
141 }
142
143 if (timing->rate < min_rate)
144 continue;
145
146 if (timing->rate >= rate)
147 return timing->rate;
148 }
149
150 if (timing)
151 return timing->rate;
152
153 return __clk_get_rate(hw->clk);
154}
155
156static u8 emc_get_parent(struct clk_hw *hw)
157{
158 struct tegra_clk_emc *tegra;
159 u32 val;
160
161 tegra = container_of(hw, struct tegra_clk_emc, hw);
162
163 val = readl(tegra->clk_regs + CLK_SOURCE_EMC);
164
165 return (val >> CLK_SOURCE_EMC_EMC_2X_CLK_SRC_SHIFT)
166 & CLK_SOURCE_EMC_EMC_2X_CLK_SRC_MASK;
167}
168
169static struct tegra_emc *emc_ensure_emc_driver(struct tegra_clk_emc *tegra)
170{
171 struct platform_device *pdev;
172
173 if (tegra->emc)
174 return tegra->emc;
175
176 if (!tegra->emc_node)
177 return NULL;
178
179 pdev = of_find_device_by_node(tegra->emc_node);
180 if (!pdev) {
181 pr_err("%s: could not get external memory controller\n",
182 __func__);
183 return NULL;
184 }
185
186 of_node_put(tegra->emc_node);
187 tegra->emc_node = NULL;
188
189 tegra->emc = platform_get_drvdata(pdev);
190 if (!tegra->emc) {
191 pr_err("%s: cannot find EMC driver\n", __func__);
192 return NULL;
193 }
194
195 return tegra->emc;
196}
197
198static int emc_set_timing(struct tegra_clk_emc *tegra,
199 struct emc_timing *timing)
200{
201 int err;
202 u8 div;
203 u32 car_value;
204 unsigned long flags = 0;
205 struct tegra_emc *emc = emc_ensure_emc_driver(tegra);
206
207 if (!emc)
208 return -ENOENT;
209
210 pr_debug("going to rate %ld prate %ld p %s\n", timing->rate,
211 timing->parent_rate, __clk_get_name(timing->parent));
212
213 if (emc_get_parent(&tegra->hw) == timing->parent_index &&
214 clk_get_rate(timing->parent) != timing->parent_rate) {
215 BUG();
216 return -EINVAL;
217 }
218
219 tegra->changing_timing = true;
220
221 err = clk_set_rate(timing->parent, timing->parent_rate);
222 if (err) {
223 pr_err("cannot change parent %s rate to %ld: %d\n",
224 __clk_get_name(timing->parent), timing->parent_rate,
225 err);
226
227 return err;
228 }
229
230 err = clk_prepare_enable(timing->parent);
231 if (err) {
232 pr_err("cannot enable parent clock: %d\n", err);
233 return err;
234 }
235
236 div = timing->parent_rate / (timing->rate / 2) - 2;
237
238 err = tegra_emc_prepare_timing_change(emc, timing->rate);
239 if (err)
240 return err;
241
242 spin_lock_irqsave(tegra->lock, flags);
243
244 car_value = readl(tegra->clk_regs + CLK_SOURCE_EMC);
245
246 car_value &= ~CLK_SOURCE_EMC_EMC_2X_CLK_SRC(~0);
247 car_value |= CLK_SOURCE_EMC_EMC_2X_CLK_SRC(timing->parent_index);
248
249 car_value &= ~CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR(~0);
250 car_value |= CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR(div);
251
252 writel(car_value, tegra->clk_regs + CLK_SOURCE_EMC);
253
254 spin_unlock_irqrestore(tegra->lock, flags);
255
256 tegra_emc_complete_timing_change(emc, timing->rate);
257
258 clk_hw_reparent(&tegra->hw, __clk_get_hw(timing->parent));
259 clk_disable_unprepare(tegra->prev_parent);
260
261 tegra->prev_parent = timing->parent;
262 tegra->changing_timing = false;
263
264 return 0;
265}
266
267/*
268 * Get backup timing to use as an intermediate step when a change between
269 * two timings with the same clock source has been requested. First try to
270 * find a timing with a higher clock rate to avoid a rate below any set rate
271 * floors. If that is not possible, find a lower rate.
272 */
273static struct emc_timing *get_backup_timing(struct tegra_clk_emc *tegra,
274 int timing_index)
275{
276 int i;
277 u32 ram_code = tegra_read_ram_code();
278 struct emc_timing *timing;
279
280 for (i = timing_index+1; i < tegra->num_timings; i++) {
281 timing = tegra->timings + i;
282 if (timing->ram_code != ram_code)
283 continue;
284
285 if (emc_parent_clk_sources[timing->parent_index] !=
286 emc_parent_clk_sources[
287 tegra->timings[timing_index].parent_index])
288 return timing;
289 }
290
291 for (i = timing_index-1; i >= 0; --i) {
292 timing = tegra->timings + i;
293 if (timing->ram_code != ram_code)
294 continue;
295
296 if (emc_parent_clk_sources[timing->parent_index] !=
297 emc_parent_clk_sources[
298 tegra->timings[timing_index].parent_index])
299 return timing;
300 }
301
302 return NULL;
303}
304
305static int emc_set_rate(struct clk_hw *hw, unsigned long rate,
306 unsigned long parent_rate)
307{
308 struct tegra_clk_emc *tegra;
309 struct emc_timing *timing = NULL;
310 int i, err;
311 u32 ram_code = tegra_read_ram_code();
312
313 tegra = container_of(hw, struct tegra_clk_emc, hw);
314
315 if (__clk_get_rate(hw->clk) == rate)
316 return 0;
317
318 /*
319 * When emc_set_timing changes the parent rate, CCF will propagate
320 * that downward to us, so ignore any set_rate calls while a rate
321 * change is already going on.
322 */
323 if (tegra->changing_timing)
324 return 0;
325
326 for (i = 0; i < tegra->num_timings; i++) {
327 if (tegra->timings[i].rate == rate &&
328 tegra->timings[i].ram_code == ram_code) {
329 timing = tegra->timings + i;
330 break;
331 }
332 }
333
334 if (!timing) {
335 pr_err("cannot switch to rate %ld without emc table\n", rate);
336 return -EINVAL;
337 }
338
339 if (emc_parent_clk_sources[emc_get_parent(hw)] ==
340 emc_parent_clk_sources[timing->parent_index] &&
341 clk_get_rate(timing->parent) != timing->parent_rate) {
342 /*
343 * Parent clock source not changed but parent rate has changed,
344 * need to temporarily switch to another parent
345 */
346
347 struct emc_timing *backup_timing;
348
349 backup_timing = get_backup_timing(tegra, i);
350 if (!backup_timing) {
351 pr_err("cannot find backup timing\n");
352 return -EINVAL;
353 }
354
355 pr_debug("using %ld as backup rate when going to %ld\n",
356 backup_timing->rate, rate);
357
358 err = emc_set_timing(tegra, backup_timing);
359 if (err) {
360 pr_err("cannot set backup timing: %d\n", err);
361 return err;
362 }
363 }
364
365 return emc_set_timing(tegra, timing);
366}
367
368/* Initialization and deinitialization */
369
370static int load_one_timing_from_dt(struct tegra_clk_emc *tegra,
371 struct emc_timing *timing,
372 struct device_node *node)
373{
374 int err, i;
375 u32 tmp;
376
377 err = of_property_read_u32(node, "clock-frequency", &tmp);
378 if (err) {
379 pr_err("timing %s: failed to read rate\n", node->full_name);
380 return err;
381 }
382
383 timing->rate = tmp;
384
385 err = of_property_read_u32(node, "nvidia,parent-clock-frequency", &tmp);
386 if (err) {
387 pr_err("timing %s: failed to read parent rate\n",
388 node->full_name);
389 return err;
390 }
391
392 timing->parent_rate = tmp;
393
394 timing->parent = of_clk_get_by_name(node, "emc-parent");
395 if (IS_ERR(timing->parent)) {
396 pr_err("timing %s: failed to get parent clock\n",
397 node->full_name);
398 return PTR_ERR(timing->parent);
399 }
400
401 timing->parent_index = 0xff;
402 for (i = 0; i < ARRAY_SIZE(emc_parent_clk_names); i++) {
403 if (!strcmp(emc_parent_clk_names[i],
404 __clk_get_name(timing->parent))) {
405 timing->parent_index = i;
406 break;
407 }
408 }
409 if (timing->parent_index == 0xff) {
410 pr_err("timing %s: %s is not a valid parent\n",
411 node->full_name, __clk_get_name(timing->parent));
412 clk_put(timing->parent);
413 return -EINVAL;
414 }
415
416 return 0;
417}
418
419static int cmp_timings(const void *_a, const void *_b)
420{
421 const struct emc_timing *a = _a;
422 const struct emc_timing *b = _b;
423
424 if (a->rate < b->rate)
425 return -1;
426 else if (a->rate == b->rate)
427 return 0;
428 else
429 return 1;
430}
431
432static int load_timings_from_dt(struct tegra_clk_emc *tegra,
433 struct device_node *node,
434 u32 ram_code)
435{
436 struct device_node *child;
437 int child_count = of_get_child_count(node);
438 int i = 0, err;
439
440 tegra->timings = kcalloc(child_count, sizeof(struct emc_timing),
441 GFP_KERNEL);
442 if (!tegra->timings)
443 return -ENOMEM;
444
445 tegra->num_timings = child_count;
446
447 for_each_child_of_node(node, child) {
448 struct emc_timing *timing = tegra->timings + (i++);
449
450 err = load_one_timing_from_dt(tegra, timing, child);
451 if (err)
452 return err;
453
454 timing->ram_code = ram_code;
455 }
456
457 sort(tegra->timings, tegra->num_timings, sizeof(struct emc_timing),
458 cmp_timings, NULL);
459
460 return 0;
461}
462
463static const struct clk_ops tegra_clk_emc_ops = {
464 .recalc_rate = emc_recalc_rate,
465 .determine_rate = emc_determine_rate,
466 .set_rate = emc_set_rate,
467 .get_parent = emc_get_parent,
468};
469
470struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
471 spinlock_t *lock)
472{
473 struct tegra_clk_emc *tegra;
474 struct clk_init_data init;
475 struct device_node *node;
476 u32 node_ram_code;
477 struct clk *clk;
478 int err;
479
480 tegra = kcalloc(1, sizeof(*tegra), GFP_KERNEL);
481 if (!tegra)
482 return ERR_PTR(-ENOMEM);
483
484 tegra->clk_regs = base;
485 tegra->lock = lock;
486
487 tegra->num_timings = 0;
488
489 for_each_child_of_node(np, node) {
490 err = of_property_read_u32(node, "nvidia,ram-code",
491 &node_ram_code);
492 if (err) {
493 of_node_put(node);
494 continue;
495 }
496
497 /*
498 * Store timings for all ram codes as we cannot read the
499 * fuses until the apbmisc driver is loaded.
500 */
501 err = load_timings_from_dt(tegra, node, node_ram_code);
502 if (err)
503 return ERR_PTR(err);
504 of_node_put(node);
505 break;
506 }
507
508 if (tegra->num_timings == 0)
509 pr_warn("%s: no memory timings registered\n", __func__);
510
511 tegra->emc_node = of_parse_phandle(np,
512 "nvidia,external-memory-controller", 0);
513 if (!tegra->emc_node)
514 pr_warn("%s: couldn't find node for EMC driver\n", __func__);
515
516 init.name = "emc";
517 init.ops = &tegra_clk_emc_ops;
518 init.flags = 0;
519 init.parent_names = emc_parent_clk_names;
520 init.num_parents = ARRAY_SIZE(emc_parent_clk_names);
521
522 tegra->hw.init = &init;
523
524 clk = clk_register(NULL, &tegra->hw);
525 if (IS_ERR(clk))
526 return clk;
527
528 tegra->prev_parent = clk_get_parent_by_index(
529 tegra->hw.clk, emc_get_parent(&tegra->hw));
530 tegra->changing_timing = false;
531
532 /* Allow debugging tools to see the EMC clock */
533 clk_register_clkdev(clk, "emc", "tegra-clk-debug");
534
535 clk_prepare_enable(clk);
536
537 return clk;
538};
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index 11f857cd5f6a..e8cca3eac007 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -152,11 +152,6 @@ static unsigned long tegra124_input_freq[] = {
152 [12] = 260000000, 152 [12] = 260000000,
153}; 153};
154 154
155static const char *mux_pllmcp_clkm[] = {
156 "pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_c2", "pll_c3",
157};
158#define mux_pllmcp_clkm_idx NULL
159
160static struct div_nmp pllxc_nmp = { 155static struct div_nmp pllxc_nmp = {
161 .divm_shift = 0, 156 .divm_shift = 0,
162 .divm_width = 8, 157 .divm_width = 8,
@@ -791,7 +786,6 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
791 [tegra_clk_i2c2] = { .dt_id = TEGRA124_CLK_I2C2, .present = true }, 786 [tegra_clk_i2c2] = { .dt_id = TEGRA124_CLK_I2C2, .present = true },
792 [tegra_clk_uartc] = { .dt_id = TEGRA124_CLK_UARTC, .present = true }, 787 [tegra_clk_uartc] = { .dt_id = TEGRA124_CLK_UARTC, .present = true },
793 [tegra_clk_mipi_cal] = { .dt_id = TEGRA124_CLK_MIPI_CAL, .present = true }, 788 [tegra_clk_mipi_cal] = { .dt_id = TEGRA124_CLK_MIPI_CAL, .present = true },
794 [tegra_clk_emc] = { .dt_id = TEGRA124_CLK_EMC, .present = true },
795 [tegra_clk_usb2] = { .dt_id = TEGRA124_CLK_USB2, .present = true }, 789 [tegra_clk_usb2] = { .dt_id = TEGRA124_CLK_USB2, .present = true },
796 [tegra_clk_usb3] = { .dt_id = TEGRA124_CLK_USB3, .present = true }, 790 [tegra_clk_usb3] = { .dt_id = TEGRA124_CLK_USB3, .present = true },
797 [tegra_clk_vde_8] = { .dt_id = TEGRA124_CLK_VDE, .present = true }, 791 [tegra_clk_vde_8] = { .dt_id = TEGRA124_CLK_VDE, .present = true },
@@ -1127,13 +1121,7 @@ static __init void tegra124_periph_clk_init(void __iomem *clk_base,
1127 periph_clk_enb_refcnt); 1121 periph_clk_enb_refcnt);
1128 clks[TEGRA124_CLK_DSIB] = clk; 1122 clks[TEGRA124_CLK_DSIB] = clk;
1129 1123
1130 /* emc mux */ 1124 clk = tegra_clk_register_mc("mc", "emc", clk_base + CLK_SOURCE_EMC,
1131 clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
1132 ARRAY_SIZE(mux_pllmcp_clkm), 0,
1133 clk_base + CLK_SOURCE_EMC,
1134 29, 3, 0, &emc_lock);
1135
1136 clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
1137 &emc_lock); 1125 &emc_lock);
1138 clks[TEGRA124_CLK_MC] = clk; 1126 clks[TEGRA124_CLK_MC] = clk;
1139 1127
@@ -1389,7 +1377,6 @@ static struct tegra_clk_init_table common_init_table[] __initdata = {
1389 {TEGRA124_CLK_XUSB_HOST_SRC, TEGRA124_CLK_PLL_RE_OUT, 112000000, 0}, 1377 {TEGRA124_CLK_XUSB_HOST_SRC, TEGRA124_CLK_PLL_RE_OUT, 112000000, 0},
1390 {TEGRA124_CLK_SATA, TEGRA124_CLK_PLL_P, 104000000, 0}, 1378 {TEGRA124_CLK_SATA, TEGRA124_CLK_PLL_P, 104000000, 0},
1391 {TEGRA124_CLK_SATA_OOB, TEGRA124_CLK_PLL_P, 204000000, 0}, 1379 {TEGRA124_CLK_SATA_OOB, TEGRA124_CLK_PLL_P, 204000000, 0},
1392 {TEGRA124_CLK_EMC, TEGRA124_CLK_CLK_MAX, 0, 1},
1393 {TEGRA124_CLK_MSELECT, TEGRA124_CLK_CLK_MAX, 0, 1}, 1380 {TEGRA124_CLK_MSELECT, TEGRA124_CLK_CLK_MAX, 0, 1},
1394 {TEGRA124_CLK_CSITE, TEGRA124_CLK_CLK_MAX, 0, 1}, 1381 {TEGRA124_CLK_CSITE, TEGRA124_CLK_CLK_MAX, 0, 1},
1395 {TEGRA124_CLK_TSENSOR, TEGRA124_CLK_CLK_M, 400000, 0}, 1382 {TEGRA124_CLK_TSENSOR, TEGRA124_CLK_CLK_M, 400000, 0},
@@ -1513,6 +1500,10 @@ static void __init tegra124_132_clock_init_post(struct device_node *np)
1513 tegra_super_clk_gen4_init(clk_base, pmc_base, tegra124_clks, 1500 tegra_super_clk_gen4_init(clk_base, pmc_base, tegra124_clks,
1514 &pll_x_params); 1501 &pll_x_params);
1515 tegra_add_of_provider(np); 1502 tegra_add_of_provider(np);
1503
1504 clks[TEGRA124_CLK_EMC] = tegra_clk_register_emc(clk_base, np,
1505 &emc_lock);
1506
1516 tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); 1507 tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
1517 1508
1518 tegra_cpu_car_ops = &tegra124_cpu_car_ops; 1509 tegra_cpu_car_ops = &tegra124_cpu_car_ops;
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index 4b26509fc218..0af3e834dd24 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -679,7 +679,7 @@ static struct tegra_devclk devclks[] __initdata = {
679 { .dev_id = "tegra30-dam.1", .dt_id = TEGRA30_CLK_DAM1 }, 679 { .dev_id = "tegra30-dam.1", .dt_id = TEGRA30_CLK_DAM1 },
680 { .dev_id = "tegra30-dam.2", .dt_id = TEGRA30_CLK_DAM2 }, 680 { .dev_id = "tegra30-dam.2", .dt_id = TEGRA30_CLK_DAM2 },
681 { .con_id = "hda", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA }, 681 { .con_id = "hda", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA },
682 { .con_id = "hda2codec", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA2CODEC_2X }, 682 { .con_id = "hda2codec_2x", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA2CODEC_2X },
683 { .dev_id = "spi_tegra.0", .dt_id = TEGRA30_CLK_SBC1 }, 683 { .dev_id = "spi_tegra.0", .dt_id = TEGRA30_CLK_SBC1 },
684 { .dev_id = "spi_tegra.1", .dt_id = TEGRA30_CLK_SBC2 }, 684 { .dev_id = "spi_tegra.1", .dt_id = TEGRA30_CLK_SBC2 },
685 { .dev_id = "spi_tegra.2", .dt_id = TEGRA30_CLK_SBC3 }, 685 { .dev_id = "spi_tegra.2", .dt_id = TEGRA30_CLK_SBC3 },
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index d6ac00647faf..75ddc8ff8bd4 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -623,6 +623,18 @@ void tegra_super_clk_gen4_init(void __iomem *clk_base,
623 void __iomem *pmc_base, struct tegra_clk *tegra_clks, 623 void __iomem *pmc_base, struct tegra_clk *tegra_clks,
624 struct tegra_clk_pll_params *pll_params); 624 struct tegra_clk_pll_params *pll_params);
625 625
626#ifdef CONFIG_TEGRA_CLK_EMC
627struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
628 spinlock_t *lock);
629#else
630static inline struct clk *tegra_clk_register_emc(void __iomem *base,
631 struct device_node *np,
632 spinlock_t *lock)
633{
634 return NULL;
635}
636#endif
637
626void tegra114_clock_tune_cpu_trimmers_high(void); 638void tegra114_clock_tune_cpu_trimmers_high(void);
627void tegra114_clock_tune_cpu_trimmers_low(void); 639void tegra114_clock_tune_cpu_trimmers_low(void);
628void tegra114_clock_tune_cpu_trimmers_init(void); 640void tegra114_clock_tune_cpu_trimmers_init(void);
diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c
index 3bf5aba4caaa..73fad05d8f2c 100644
--- a/drivers/soc/tegra/fuse/tegra-apbmisc.c
+++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c
@@ -28,8 +28,15 @@
28#define APBMISC_SIZE 0x64 28#define APBMISC_SIZE 0x64
29#define FUSE_SKU_INFO 0x10 29#define FUSE_SKU_INFO 0x10
30 30
31#define PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT 4
32#define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG \
33 (0xf << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT)
34#define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT \
35 (0x3 << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT)
36
31static void __iomem *apbmisc_base; 37static void __iomem *apbmisc_base;
32static void __iomem *strapping_base; 38static void __iomem *strapping_base;
39static bool long_ram_code;
33 40
34u32 tegra_read_chipid(void) 41u32 tegra_read_chipid(void)
35{ 42{
@@ -54,6 +61,18 @@ u32 tegra_read_straps(void)
54 return 0; 61 return 0;
55} 62}
56 63
64u32 tegra_read_ram_code(void)
65{
66 u32 straps = tegra_read_straps();
67
68 if (long_ram_code)
69 straps &= PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG;
70 else
71 straps &= PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT;
72
73 return straps >> PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT;
74}
75
57static const struct of_device_id apbmisc_match[] __initconst = { 76static const struct of_device_id apbmisc_match[] __initconst = {
58 { .compatible = "nvidia,tegra20-apbmisc", }, 77 { .compatible = "nvidia,tegra20-apbmisc", },
59 {}, 78 {},
@@ -112,4 +131,6 @@ void __init tegra_init_apbmisc(void)
112 strapping_base = of_iomap(np, 1); 131 strapping_base = of_iomap(np, 1);
113 if (!strapping_base) 132 if (!strapping_base)
114 pr_err("ioremap tegra strapping_base failed\n"); 133 pr_err("ioremap tegra strapping_base failed\n");
134
135 long_ram_code = of_property_read_bool(np, "nvidia,long-ram-code");
115} 136}
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 6a24df64b0a0..78842f46f152 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -592,6 +592,7 @@ long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
592 unsigned long max_rate, 592 unsigned long max_rate,
593 unsigned long *best_parent_rate, 593 unsigned long *best_parent_rate,
594 struct clk_hw **best_parent_p); 594 struct clk_hw **best_parent_p);
595void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent);
595 596
596static inline void __clk_hw_set_clk(struct clk_hw *dst, struct clk_hw *src) 597static inline void __clk_hw_set_clk(struct clk_hw *dst, struct clk_hw *src)
597{ 598{
diff --git a/include/soc/tegra/fuse.h b/include/soc/tegra/fuse.h
index b5f7b5f8d008..b019e3465f11 100644
--- a/include/soc/tegra/fuse.h
+++ b/include/soc/tegra/fuse.h
@@ -56,6 +56,7 @@ struct tegra_sku_info {
56}; 56};
57 57
58u32 tegra_read_straps(void); 58u32 tegra_read_straps(void);
59u32 tegra_read_ram_code(void);
59u32 tegra_read_chipid(void); 60u32 tegra_read_chipid(void);
60int tegra_fuse_readl(unsigned long offset, u32 *value); 61int tegra_fuse_readl(unsigned long offset, u32 *value);
61 62