tangled
alpha
login
or
join now
tjh.dev
/
kernel
1
fork
atom
Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1
fork
atom
overview
issues
pulls
pipelines
Merge branch 'for-5.5/clk' into for-5.5/memory
Thierry Reding
6 years ago
3feb4a3c
54ecb8f7
+350
-52
6 changed files
expand all
collapse all
unified
split
drivers
clk
tegra
Makefile
clk-tegra20-emc.c
clk-tegra20.c
clk-tegra30.c
clk.h
include
linux
clk
tegra.h
+2
drivers/clk/tegra/Makefile
reviewed
···
17
17
obj-y += clk-tegra-super-gen4.o
18
18
obj-$(CONFIG_TEGRA_CLK_EMC) += clk-emc.o
19
19
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o
20
20
+
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20-emc.o
20
21
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o
22
22
+
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra20-emc.o
21
23
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o
22
24
obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124.o
23
25
obj-$(CONFIG_TEGRA_CLK_DFLL) += clk-tegra124-dfll-fcpu.o
+293
drivers/clk/tegra/clk-tegra20-emc.c
reviewed
···
1
1
+
// SPDX-License-Identifier: GPL-2.0+
2
2
+
/*
3
3
+
* Based on drivers/clk/tegra/clk-emc.c
4
4
+
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
5
5
+
*
6
6
+
* Author: Dmitry Osipenko <digetx@gmail.com>
7
7
+
* Copyright (C) 2019 GRATE-DRIVER project
8
8
+
*/
9
9
+
10
10
+
#define pr_fmt(fmt) "tegra-emc-clk: " fmt
11
11
+
12
12
+
#include <linux/bits.h>
13
13
+
#include <linux/clk-provider.h>
14
14
+
#include <linux/clk/tegra.h>
15
15
+
#include <linux/err.h>
16
16
+
#include <linux/io.h>
17
17
+
#include <linux/kernel.h>
18
18
+
#include <linux/slab.h>
19
19
+
20
20
+
#include "clk.h"
21
21
+
22
22
+
#define CLK_SOURCE_EMC_2X_CLK_DIVISOR_MASK GENMASK(7, 0)
23
23
+
#define CLK_SOURCE_EMC_2X_CLK_SRC_MASK GENMASK(31, 30)
24
24
+
#define CLK_SOURCE_EMC_2X_CLK_SRC_SHIFT 30
25
25
+
26
26
+
#define MC_EMC_SAME_FREQ BIT(16)
27
27
+
#define USE_PLLM_UD BIT(29)
28
28
+
29
29
+
#define EMC_SRC_PLL_M 0
30
30
+
#define EMC_SRC_PLL_C 1
31
31
+
#define EMC_SRC_PLL_P 2
32
32
+
#define EMC_SRC_CLK_M 3
33
33
+
34
34
+
static const char * const emc_parent_clk_names[] = {
35
35
+
"pll_m", "pll_c", "pll_p", "clk_m",
36
36
+
};
37
37
+
38
38
+
struct tegra_clk_emc {
39
39
+
struct clk_hw hw;
40
40
+
void __iomem *reg;
41
41
+
bool mc_same_freq;
42
42
+
bool want_low_jitter;
43
43
+
44
44
+
tegra20_clk_emc_round_cb *round_cb;
45
45
+
void *cb_arg;
46
46
+
};
47
47
+
48
48
+
static inline struct tegra_clk_emc *to_tegra_clk_emc(struct clk_hw *hw)
49
49
+
{
50
50
+
return container_of(hw, struct tegra_clk_emc, hw);
51
51
+
}
52
52
+
53
53
+
static unsigned long emc_recalc_rate(struct clk_hw *hw,
54
54
+
unsigned long parent_rate)
55
55
+
{
56
56
+
struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
57
57
+
u32 val, div;
58
58
+
59
59
+
val = readl_relaxed(emc->reg);
60
60
+
div = val & CLK_SOURCE_EMC_2X_CLK_DIVISOR_MASK;
61
61
+
62
62
+
return DIV_ROUND_UP(parent_rate * 2, div + 2);
63
63
+
}
64
64
+
65
65
+
static u8 emc_get_parent(struct clk_hw *hw)
66
66
+
{
67
67
+
struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
68
68
+
69
69
+
return readl_relaxed(emc->reg) >> CLK_SOURCE_EMC_2X_CLK_SRC_SHIFT;
70
70
+
}
71
71
+
72
72
+
static int emc_set_parent(struct clk_hw *hw, u8 index)
73
73
+
{
74
74
+
struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
75
75
+
u32 val, div;
76
76
+
77
77
+
val = readl_relaxed(emc->reg);
78
78
+
val &= ~CLK_SOURCE_EMC_2X_CLK_SRC_MASK;
79
79
+
val |= index << CLK_SOURCE_EMC_2X_CLK_SRC_SHIFT;
80
80
+
81
81
+
div = val & CLK_SOURCE_EMC_2X_CLK_DIVISOR_MASK;
82
82
+
83
83
+
if (index == EMC_SRC_PLL_M && div == 0 && emc->want_low_jitter)
84
84
+
val |= USE_PLLM_UD;
85
85
+
else
86
86
+
val &= ~USE_PLLM_UD;
87
87
+
88
88
+
if (emc->mc_same_freq)
89
89
+
val |= MC_EMC_SAME_FREQ;
90
90
+
else
91
91
+
val &= ~MC_EMC_SAME_FREQ;
92
92
+
93
93
+
writel_relaxed(val, emc->reg);
94
94
+
95
95
+
fence_udelay(1, emc->reg);
96
96
+
97
97
+
return 0;
98
98
+
}
99
99
+
100
100
+
static int emc_set_rate(struct clk_hw *hw, unsigned long rate,
101
101
+
unsigned long parent_rate)
102
102
+
{
103
103
+
struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
104
104
+
unsigned int index;
105
105
+
u32 val, div;
106
106
+
107
107
+
div = div_frac_get(rate, parent_rate, 8, 1, 0);
108
108
+
109
109
+
val = readl_relaxed(emc->reg);
110
110
+
val &= ~CLK_SOURCE_EMC_2X_CLK_DIVISOR_MASK;
111
111
+
val |= div;
112
112
+
113
113
+
index = val >> CLK_SOURCE_EMC_2X_CLK_SRC_SHIFT;
114
114
+
115
115
+
if (index == EMC_SRC_PLL_M && div == 0 && emc->want_low_jitter)
116
116
+
val |= USE_PLLM_UD;
117
117
+
else
118
118
+
val &= ~USE_PLLM_UD;
119
119
+
120
120
+
if (emc->mc_same_freq)
121
121
+
val |= MC_EMC_SAME_FREQ;
122
122
+
else
123
123
+
val &= ~MC_EMC_SAME_FREQ;
124
124
+
125
125
+
writel_relaxed(val, emc->reg);
126
126
+
127
127
+
fence_udelay(1, emc->reg);
128
128
+
129
129
+
return 0;
130
130
+
}
131
131
+
132
132
+
static int emc_set_rate_and_parent(struct clk_hw *hw,
133
133
+
unsigned long rate,
134
134
+
unsigned long parent_rate,
135
135
+
u8 index)
136
136
+
{
137
137
+
struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
138
138
+
u32 val, div;
139
139
+
140
140
+
div = div_frac_get(rate, parent_rate, 8, 1, 0);
141
141
+
142
142
+
val = readl_relaxed(emc->reg);
143
143
+
144
144
+
val &= ~CLK_SOURCE_EMC_2X_CLK_SRC_MASK;
145
145
+
val |= index << CLK_SOURCE_EMC_2X_CLK_SRC_SHIFT;
146
146
+
147
147
+
val &= ~CLK_SOURCE_EMC_2X_CLK_DIVISOR_MASK;
148
148
+
val |= div;
149
149
+
150
150
+
if (index == EMC_SRC_PLL_M && div == 0 && emc->want_low_jitter)
151
151
+
val |= USE_PLLM_UD;
152
152
+
else
153
153
+
val &= ~USE_PLLM_UD;
154
154
+
155
155
+
if (emc->mc_same_freq)
156
156
+
val |= MC_EMC_SAME_FREQ;
157
157
+
else
158
158
+
val &= ~MC_EMC_SAME_FREQ;
159
159
+
160
160
+
writel_relaxed(val, emc->reg);
161
161
+
162
162
+
fence_udelay(1, emc->reg);
163
163
+
164
164
+
return 0;
165
165
+
}
166
166
+
167
167
+
static int emc_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
168
168
+
{
169
169
+
struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
170
170
+
struct clk_hw *parent_hw;
171
171
+
unsigned long divided_rate;
172
172
+
unsigned long parent_rate;
173
173
+
unsigned int i;
174
174
+
long emc_rate;
175
175
+
int div;
176
176
+
177
177
+
emc_rate = emc->round_cb(req->rate, req->min_rate, req->max_rate,
178
178
+
emc->cb_arg);
179
179
+
if (emc_rate < 0)
180
180
+
return emc_rate;
181
181
+
182
182
+
for (i = 0; i < ARRAY_SIZE(emc_parent_clk_names); i++) {
183
183
+
parent_hw = clk_hw_get_parent_by_index(hw, i);
184
184
+
185
185
+
if (req->best_parent_hw == parent_hw)
186
186
+
parent_rate = req->best_parent_rate;
187
187
+
else
188
188
+
parent_rate = clk_hw_get_rate(parent_hw);
189
189
+
190
190
+
if (emc_rate > parent_rate)
191
191
+
continue;
192
192
+
193
193
+
div = div_frac_get(emc_rate, parent_rate, 8, 1, 0);
194
194
+
divided_rate = DIV_ROUND_UP(parent_rate * 2, div + 2);
195
195
+
196
196
+
if (divided_rate != emc_rate)
197
197
+
continue;
198
198
+
199
199
+
req->best_parent_rate = parent_rate;
200
200
+
req->best_parent_hw = parent_hw;
201
201
+
req->rate = emc_rate;
202
202
+
break;
203
203
+
}
204
204
+
205
205
+
if (i == ARRAY_SIZE(emc_parent_clk_names)) {
206
206
+
pr_err_once("can't find parent for rate %lu emc_rate %lu\n",
207
207
+
req->rate, emc_rate);
208
208
+
return -EINVAL;
209
209
+
}
210
210
+
211
211
+
return 0;
212
212
+
}
213
213
+
214
214
+
static const struct clk_ops tegra_clk_emc_ops = {
215
215
+
.recalc_rate = emc_recalc_rate,
216
216
+
.get_parent = emc_get_parent,
217
217
+
.set_parent = emc_set_parent,
218
218
+
.set_rate = emc_set_rate,
219
219
+
.set_rate_and_parent = emc_set_rate_and_parent,
220
220
+
.determine_rate = emc_determine_rate,
221
221
+
};
222
222
+
223
223
+
void tegra20_clk_set_emc_round_callback(tegra20_clk_emc_round_cb *round_cb,
224
224
+
void *cb_arg)
225
225
+
{
226
226
+
struct clk *clk = __clk_lookup("emc");
227
227
+
struct tegra_clk_emc *emc;
228
228
+
struct clk_hw *hw;
229
229
+
230
230
+
if (clk) {
231
231
+
hw = __clk_get_hw(clk);
232
232
+
emc = to_tegra_clk_emc(hw);
233
233
+
234
234
+
emc->round_cb = round_cb;
235
235
+
emc->cb_arg = cb_arg;
236
236
+
}
237
237
+
}
238
238
+
239
239
+
bool tegra20_clk_emc_driver_available(struct clk_hw *emc_hw)
240
240
+
{
241
241
+
return to_tegra_clk_emc(emc_hw)->round_cb != NULL;
242
242
+
}
243
243
+
244
244
+
struct clk *tegra20_clk_register_emc(void __iomem *ioaddr, bool low_jitter)
245
245
+
{
246
246
+
struct tegra_clk_emc *emc;
247
247
+
struct clk_init_data init;
248
248
+
struct clk *clk;
249
249
+
250
250
+
emc = kzalloc(sizeof(*emc), GFP_KERNEL);
251
251
+
if (!emc)
252
252
+
return NULL;
253
253
+
254
254
+
/*
255
255
+
* EMC stands for External Memory Controller.
256
256
+
*
257
257
+
* We don't want EMC clock to be disabled ever by gating its
258
258
+
* parent and whatnot because system is busted immediately in that
259
259
+
* case, hence the clock is marked as critical.
260
260
+
*/
261
261
+
init.name = "emc";
262
262
+
init.ops = &tegra_clk_emc_ops;
263
263
+
init.flags = CLK_IS_CRITICAL;
264
264
+
init.parent_names = emc_parent_clk_names;
265
265
+
init.num_parents = ARRAY_SIZE(emc_parent_clk_names);
266
266
+
267
267
+
emc->reg = ioaddr;
268
268
+
emc->hw.init = &init;
269
269
+
emc->want_low_jitter = low_jitter;
270
270
+
271
271
+
clk = clk_register(NULL, &emc->hw);
272
272
+
if (IS_ERR(clk)) {
273
273
+
kfree(emc);
274
274
+
return NULL;
275
275
+
}
276
276
+
277
277
+
return clk;
278
278
+
}
279
279
+
280
280
+
int tegra20_clk_prepare_emc_mc_same_freq(struct clk *emc_clk, bool same)
281
281
+
{
282
282
+
struct tegra_clk_emc *emc;
283
283
+
struct clk_hw *hw;
284
284
+
285
285
+
if (!emc_clk)
286
286
+
return -EINVAL;
287
287
+
288
288
+
hw = __clk_get_hw(emc_clk);
289
289
+
emc = to_tegra_clk_emc(hw);
290
290
+
emc->mc_same_freq = same;
291
291
+
292
292
+
return 0;
293
293
+
}
+14
-41
drivers/clk/tegra/clk-tegra20.c
reviewed
···
130
130
static void __iomem *clk_base;
131
131
static void __iomem *pmc_base;
132
132
133
133
-
static DEFINE_SPINLOCK(emc_lock);
134
134
-
135
133
#define TEGRA_INIT_DATA_MUX(_name, _parents, _offset, \
136
134
_clk_num, _gate_flags, _clk_id) \
137
135
TEGRA_INIT_DATA(_name, NULL, NULL, _parents, _offset, \
···
758
760
static const char *mux_pllpcm_clkm[] = { "pll_p", "pll_c", "pll_m", "clk_m" };
759
761
static const char *mux_pllpdc_clkm[] = { "pll_p", "pll_d_out0", "pll_c",
760
762
"clk_m" };
761
761
-
static const char *mux_pllmcp_clkm[] = { "pll_m", "pll_c", "pll_p", "clk_m" };
762
763
763
764
static struct tegra_periph_init_data tegra_periph_clk_list[] = {
764
765
TEGRA_INIT_DATA_MUX("i2s1", i2s1_parents, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_I2S1),
···
784
787
TEGRA_INIT_DATA_NODIV("disp2", mux_pllpdc_clkm, CLK_SOURCE_DISP2, 30, 2, 26, 0, TEGRA20_CLK_DISP2),
785
788
};
786
789
787
787
-
static void __init tegra20_emc_clk_init(void)
788
788
-
{
789
789
-
const u32 use_pllm_ud = BIT(29);
790
790
-
struct clk *clk;
791
791
-
u32 emc_reg;
792
792
-
793
793
-
clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
794
794
-
ARRAY_SIZE(mux_pllmcp_clkm),
795
795
-
CLK_SET_RATE_NO_REPARENT,
796
796
-
clk_base + CLK_SOURCE_EMC,
797
797
-
30, 2, 0, &emc_lock);
798
798
-
799
799
-
clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
800
800
-
&emc_lock);
801
801
-
clks[TEGRA20_CLK_MC] = clk;
802
802
-
803
803
-
/* un-divided pll_m_out0 is currently unsupported */
804
804
-
emc_reg = readl_relaxed(clk_base + CLK_SOURCE_EMC);
805
805
-
if (emc_reg & use_pllm_ud) {
806
806
-
pr_err("%s: un-divided PllM_out0 used as clock source\n",
807
807
-
__func__);
808
808
-
return;
809
809
-
}
810
810
-
811
811
-
/*
812
812
-
* Note that 'emc_mux' source and 'emc' rate shouldn't be changed at
813
813
-
* the same time due to a HW bug, this won't happen because we're
814
814
-
* defining 'emc_mux' and 'emc' as distinct clocks.
815
815
-
*/
816
816
-
clk = tegra_clk_register_divider("emc", "emc_mux",
817
817
-
clk_base + CLK_SOURCE_EMC, CLK_IS_CRITICAL,
818
818
-
TEGRA_DIVIDER_INT, 0, 8, 1, &emc_lock);
819
819
-
clks[TEGRA20_CLK_EMC] = clk;
820
820
-
}
821
821
-
822
790
static void __init tegra20_periph_clk_init(void)
823
791
{
824
792
struct tegra_periph_init_data *data;
···
797
835
clks[TEGRA20_CLK_AC97] = clk;
798
836
799
837
/* emc */
800
800
-
tegra20_emc_clk_init();
838
838
+
clk = tegra20_clk_register_emc(clk_base + CLK_SOURCE_EMC, false);
839
839
+
840
840
+
clks[TEGRA20_CLK_EMC] = clk;
841
841
+
842
842
+
clk = tegra_clk_register_mc("mc", "emc", clk_base + CLK_SOURCE_EMC,
843
843
+
NULL);
844
844
+
clks[TEGRA20_CLK_MC] = clk;
801
845
802
846
/* dsi */
803
847
clk = tegra_clk_register_periph_gate("dsi", "pll_d", 0, clk_base, 0,
···
1083
1115
if (IS_ERR(clk))
1084
1116
return clk;
1085
1117
1118
1118
+
hw = __clk_get_hw(clk);
1119
1119
+
1086
1120
/*
1087
1121
* Tegra20 CDEV1 and CDEV2 clocks are a bit special case, their parent
1088
1122
* clock is created by the pinctrl driver. It is possible for clk user
···
1094
1124
*/
1095
1125
if (clkspec->args[0] == TEGRA20_CLK_CDEV1 ||
1096
1126
clkspec->args[0] == TEGRA20_CLK_CDEV2) {
1097
1097
-
hw = __clk_get_hw(clk);
1098
1098
-
1099
1127
parent_hw = clk_hw_get_parent(hw);
1100
1128
if (!parent_hw)
1129
1129
+
return ERR_PTR(-EPROBE_DEFER);
1130
1130
+
}
1131
1131
+
1132
1132
+
if (clkspec->args[0] == TEGRA20_CLK_EMC) {
1133
1133
+
if (!tegra20_clk_emc_driver_available(hw))
1101
1134
return ERR_PTR(-EPROBE_DEFER);
1102
1135
}
1103
1136
+27
-11
drivers/clk/tegra/clk-tegra30.c
reviewed
···
151
151
152
152
static DEFINE_SPINLOCK(cml_lock);
153
153
static DEFINE_SPINLOCK(pll_d_lock);
154
154
-
static DEFINE_SPINLOCK(emc_lock);
155
154
156
155
#define TEGRA_INIT_DATA_MUX(_name, _parents, _offset, \
157
156
_clk_num, _gate_flags, _clk_id) \
···
807
808
[tegra_clk_pll_a] = { .dt_id = TEGRA30_CLK_PLL_A, .present = true },
808
809
[tegra_clk_pll_a_out0] = { .dt_id = TEGRA30_CLK_PLL_A_OUT0, .present = true },
809
810
[tegra_clk_cec] = { .dt_id = TEGRA30_CLK_CEC, .present = true },
810
810
-
[tegra_clk_emc] = { .dt_id = TEGRA30_CLK_EMC, .present = true },
811
811
+
[tegra_clk_emc] = { .dt_id = TEGRA30_CLK_EMC, .present = false },
811
812
};
812
813
813
814
static const char *pll_e_parents[] = { "pll_ref", "pll_p" };
···
994
995
static const char *mux_pllacp_clkm[] = { "pll_a_out0", "unused", "pll_p",
995
996
"clk_m" };
996
997
static const char *mux_pllpcm_clkm[] = { "pll_p", "pll_c", "pll_m", "clk_m" };
997
997
-
static const char *mux_pllmcp_clkm[] = { "pll_m", "pll_c", "pll_p", "clk_m" };
998
998
static const char *spdif_out_parents[] = { "pll_a_out0", "spdif_2x", "pll_p",
999
999
"clk_m" };
1000
1000
static const char *mux_pllmcpa[] = { "pll_m", "pll_c", "pll_p", "pll_a_out0" };
···
1042
1044
clks[TEGRA30_CLK_AFI] = clk;
1043
1045
1044
1046
/* emc */
1045
1045
-
clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
1046
1046
-
ARRAY_SIZE(mux_pllmcp_clkm),
1047
1047
-
CLK_SET_RATE_NO_REPARENT,
1048
1048
-
clk_base + CLK_SOURCE_EMC,
1049
1049
-
30, 2, 0, &emc_lock);
1047
1047
+
clk = tegra20_clk_register_emc(clk_base + CLK_SOURCE_EMC, true);
1050
1048
1051
1051
-
clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
1052
1052
-
&emc_lock);
1049
1049
+
clks[TEGRA30_CLK_EMC] = clk;
1050
1050
+
1051
1051
+
clk = tegra_clk_register_mc("mc", "emc", clk_base + CLK_SOURCE_EMC,
1052
1052
+
NULL);
1053
1053
clks[TEGRA30_CLK_MC] = clk;
1054
1054
1055
1055
/* cml0 */
···
1298
1302
{ "pll_a", &pll_a_params, tegra_clk_pll_a, "pll_p_out1" },
1299
1303
};
1300
1304
1305
1305
+
static struct clk *tegra30_clk_src_onecell_get(struct of_phandle_args *clkspec,
1306
1306
+
void *data)
1307
1307
+
{
1308
1308
+
struct clk_hw *hw;
1309
1309
+
struct clk *clk;
1310
1310
+
1311
1311
+
clk = of_clk_src_onecell_get(clkspec, data);
1312
1312
+
if (IS_ERR(clk))
1313
1313
+
return clk;
1314
1314
+
1315
1315
+
hw = __clk_get_hw(clk);
1316
1316
+
1317
1317
+
if (clkspec->args[0] == TEGRA30_CLK_EMC) {
1318
1318
+
if (!tegra20_clk_emc_driver_available(hw))
1319
1319
+
return ERR_PTR(-EPROBE_DEFER);
1320
1320
+
}
1321
1321
+
1322
1322
+
return clk;
1323
1323
+
}
1324
1324
+
1301
1325
static void __init tegra30_clock_init(struct device_node *np)
1302
1326
{
1303
1327
struct device_node *node;
···
1361
1345
1362
1346
tegra_init_dup_clks(tegra_clk_duplicates, clks, TEGRA30_CLK_CLK_MAX);
1363
1347
1364
1364
-
tegra_add_of_provider(np, of_clk_src_onecell_get);
1348
1348
+
tegra_add_of_provider(np, tegra30_clk_src_onecell_get);
1365
1349
tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
1366
1350
1367
1351
tegra_clk_apply_init_table = tegra30_clock_apply_init_table;
+3
drivers/clk/tegra/clk.h
reviewed
···
838
838
udelay(delay); \
839
839
} while (0)
840
840
841
841
+
bool tegra20_clk_emc_driver_available(struct clk_hw *emc_hw);
842
842
+
struct clk *tegra20_clk_register_emc(void __iomem *ioaddr, bool low_jitter);
843
843
+
841
844
#endif /* TEGRA_CLK_H */
+11
include/linux/clk/tegra.h
reviewed
···
119
119
extern void tegra210_put_utmipll_out_iddq(void);
120
120
extern int tegra210_clk_handle_mbist_war(unsigned int id);
121
121
122
122
+
struct clk;
123
123
+
124
124
+
typedef long (tegra20_clk_emc_round_cb)(unsigned long rate,
125
125
+
unsigned long min_rate,
126
126
+
unsigned long max_rate,
127
127
+
void *arg);
128
128
+
129
129
+
void tegra20_clk_set_emc_round_callback(tegra20_clk_emc_round_cb *round_cb,
130
130
+
void *cb_arg);
131
131
+
int tegra20_clk_prepare_emc_mc_same_freq(struct clk *emc_clk, bool same);
132
132
+
122
133
#endif /* __LINUX_CLK_TEGRA_H_ */