aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPeter De Schrijver <pdeschrijver@nvidia.com>2013-10-15 10:19:13 -0400
committerPeter De Schrijver <pdeschrijver@nvidia.com>2013-11-26 11:46:49 -0500
commitde4f30fd8403cd67449fbb9dc06a3d898fb9f10c (patch)
treeb3de7152b5f04afe69b272c6e45dce33c91fae32 /drivers
parent76ebc134d45d7e6e1dc29fdcef4e539c5bc76eb8 (diff)
clk: tegra: move PMC, fixed clocks to common files
Introduce new files for fixed and PMC clocks common between several Tegra SoCs and move Tegra114 to this new infrastructure. Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/tegra/Makefile2
-rw-r--r--drivers/clk/tegra/clk-tegra-fixed.c111
-rw-r--r--drivers/clk/tegra/clk-tegra-pmc.c132
-rw-r--r--drivers/clk/tegra/clk-tegra114.c75
-rw-r--r--drivers/clk/tegra/clk.h7
5 files changed, 253 insertions, 74 deletions
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
index 304ea5df63eb..a02e9a95a4cb 100644
--- a/drivers/clk/tegra/Makefile
+++ b/drivers/clk/tegra/Makefile
@@ -8,6 +8,8 @@ obj-y += clk-pll-out.o
8obj-y += clk-super.o 8obj-y += clk-super.o
9obj-y += clk-tegra-audio.o 9obj-y += clk-tegra-audio.o
10obj-y += clk-tegra-periph.o 10obj-y += clk-tegra-periph.o
11obj-y += clk-tegra-pmc.o
12obj-y += clk-tegra-fixed.o
11obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o 13obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o
12obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o 14obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o
13obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o 15obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o
diff --git a/drivers/clk/tegra/clk-tegra-fixed.c b/drivers/clk/tegra/clk-tegra-fixed.c
new file mode 100644
index 000000000000..f3b773833429
--- /dev/null
+++ b/drivers/clk/tegra/clk-tegra-fixed.c
@@ -0,0 +1,111 @@
1/*
2 * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/io.h>
18#include <linux/clk.h>
19#include <linux/clk-provider.h>
20#include <linux/of.h>
21#include <linux/of_address.h>
22#include <linux/delay.h>
23#include <linux/export.h>
24#include <linux/clk/tegra.h>
25
26#include "clk.h"
27#include "clk-id.h"
28
29#define OSC_CTRL 0x50
30#define OSC_CTRL_OSC_FREQ_SHIFT 28
31#define OSC_CTRL_PLL_REF_DIV_SHIFT 26
32
33int __init tegra_osc_clk_init(void __iomem *clk_base,
34 struct tegra_clk *tegra_clks,
35 unsigned long *input_freqs, int num,
36 unsigned long *osc_freq,
37 unsigned long *pll_ref_freq)
38{
39 struct clk *clk;
40 struct clk **dt_clk;
41 u32 val, pll_ref_div;
42 unsigned osc_idx;
43
44 val = readl_relaxed(clk_base + OSC_CTRL);
45 osc_idx = val >> OSC_CTRL_OSC_FREQ_SHIFT;
46
47 if (osc_idx < num)
48 *osc_freq = input_freqs[osc_idx];
49 else
50 *osc_freq = 0;
51
52 if (!*osc_freq) {
53 WARN_ON(1);
54 return -EINVAL;
55 }
56
57 dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m, tegra_clks);
58 if (!dt_clk)
59 return 0;
60
61 clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT,
62 *osc_freq);
63 *dt_clk = clk;
64
65 /* pll_ref */
66 val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3;
67 pll_ref_div = 1 << val;
68 dt_clk = tegra_lookup_dt_id(tegra_clk_pll_ref, tegra_clks);
69 if (!dt_clk)
70 return 0;
71
72 clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m",
73 0, 1, pll_ref_div);
74 *dt_clk = clk;
75
76 if (pll_ref_freq)
77 *pll_ref_freq = *osc_freq / pll_ref_div;
78
79 return 0;
80}
81
82void __init tegra_fixed_clk_init(struct tegra_clk *tegra_clks)
83{
84 struct clk *clk;
85 struct clk **dt_clk;
86
87 /* clk_32k */
88 dt_clk = tegra_lookup_dt_id(tegra_clk_clk_32k, tegra_clks);
89 if (dt_clk) {
90 clk = clk_register_fixed_rate(NULL, "clk_32k", NULL,
91 CLK_IS_ROOT, 32768);
92 *dt_clk = clk;
93 }
94
95 /* clk_m_div2 */
96 dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m_div2, tegra_clks);
97 if (dt_clk) {
98 clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m",
99 CLK_SET_RATE_PARENT, 1, 2);
100 *dt_clk = clk;
101 }
102
103 /* clk_m_div4 */
104 dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m_div4, tegra_clks);
105 if (dt_clk) {
106 clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m",
107 CLK_SET_RATE_PARENT, 1, 4);
108 *dt_clk = clk;
109 }
110}
111
diff --git a/drivers/clk/tegra/clk-tegra-pmc.c b/drivers/clk/tegra/clk-tegra-pmc.c
new file mode 100644
index 000000000000..08b21c1ee867
--- /dev/null
+++ b/drivers/clk/tegra/clk-tegra-pmc.c
@@ -0,0 +1,132 @@
1/*
2 * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/io.h>
18#include <linux/clk.h>
19#include <linux/clk-provider.h>
20#include <linux/clkdev.h>
21#include <linux/of.h>
22#include <linux/of_address.h>
23#include <linux/delay.h>
24#include <linux/export.h>
25#include <linux/clk/tegra.h>
26
27#include "clk.h"
28#include "clk-id.h"
29
30#define PMC_CLK_OUT_CNTRL 0x1a8
31#define PMC_DPD_PADS_ORIDE 0x1c
32#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
33#define PMC_CTRL 0
34#define PMC_CTRL_BLINK_ENB 7
35#define PMC_BLINK_TIMER 0x40
36
37struct pmc_clk_init_data {
38 char *mux_name;
39 char *gate_name;
40 const char **parents;
41 int num_parents;
42 int mux_id;
43 int gate_id;
44 char *dev_name;
45 u8 mux_shift;
46 u8 gate_shift;
47};
48
49#define PMC_CLK(_num, _mux_shift, _gate_shift)\
50 {\
51 .mux_name = "clk_out_" #_num "_mux",\
52 .gate_name = "clk_out_" #_num,\
53 .parents = clk_out ##_num ##_parents,\
54 .num_parents = ARRAY_SIZE(clk_out ##_num ##_parents),\
55 .mux_id = tegra_clk_clk_out_ ##_num ##_mux,\
56 .gate_id = tegra_clk_clk_out_ ##_num,\
57 .dev_name = "extern" #_num,\
58 .mux_shift = _mux_shift,\
59 .gate_shift = _gate_shift,\
60 }
61
62static DEFINE_SPINLOCK(clk_out_lock);
63
64static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2",
65 "clk_m_div4", "extern1",
66};
67
68static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2",
69 "clk_m_div4", "extern2",
70};
71
72static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2",
73 "clk_m_div4", "extern3",
74};
75
76static struct pmc_clk_init_data pmc_clks[] = {
77 PMC_CLK(1, 6, 2),
78 PMC_CLK(2, 14, 10),
79 PMC_CLK(3, 22, 18),
80};
81
82void __init tegra_pmc_clk_init(void __iomem *pmc_base,
83 struct tegra_clk *tegra_clks)
84{
85 struct clk *clk;
86 struct clk **dt_clk;
87 int i;
88
89 for (i = 0; i < ARRAY_SIZE(pmc_clks); i++) {
90 struct pmc_clk_init_data *data;
91
92 data = pmc_clks + i;
93
94 dt_clk = tegra_lookup_dt_id(data->mux_id, tegra_clks);
95 if (!dt_clk)
96 continue;
97
98 clk = clk_register_mux(NULL, data->mux_name, data->parents,
99 data->num_parents, CLK_SET_RATE_NO_REPARENT,
100 pmc_base + PMC_CLK_OUT_CNTRL, data->mux_shift,
101 3, 0, &clk_out_lock);
102 *dt_clk = clk;
103
104
105 dt_clk = tegra_lookup_dt_id(data->gate_id, tegra_clks);
106 if (!dt_clk)
107 continue;
108
109 clk = clk_register_gate(NULL, data->gate_name, data->mux_name,
110 0, pmc_base + PMC_CLK_OUT_CNTRL,
111 data->gate_shift, 0, &clk_out_lock);
112 *dt_clk = clk;
113 clk_register_clkdev(clk, data->dev_name, data->gate_name);
114 }
115
116 /* blink */
117 writel_relaxed(0, pmc_base + PMC_BLINK_TIMER);
118 clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0,
119 pmc_base + PMC_DPD_PADS_ORIDE,
120 PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL);
121
122 dt_clk = tegra_lookup_dt_id(tegra_clk_blink, tegra_clks);
123 if (!dt_clk)
124 return;
125
126 clk = clk_register_gate(NULL, "blink", "blink_override", 0,
127 pmc_base + PMC_CTRL,
128 PMC_CTRL_BLINK_ENB, 0, NULL);
129 clk_register_clkdev(clk, "blink", NULL);
130 *dt_clk = clk;
131}
132
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
index 07098597db53..046dbed0c2c5 100644
--- a/drivers/clk/tegra/clk-tegra114.c
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -107,13 +107,6 @@
107#define PLLC_OUT 0x84 107#define PLLC_OUT 0x84
108#define PLLM_OUT 0x94 108#define PLLM_OUT 0x94
109 109
110#define PMC_CLK_OUT_CNTRL 0x1a8
111#define PMC_DPD_PADS_ORIDE 0x1c
112#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
113#define PMC_CTRL 0
114#define PMC_CTRL_BLINK_ENB 7
115#define PMC_BLINK_TIMER 0x40
116
117#define OSC_CTRL 0x50 110#define OSC_CTRL 0x50
118#define OSC_CTRL_OSC_FREQ_SHIFT 28 111#define OSC_CTRL_OSC_FREQ_SHIFT 28
119#define OSC_CTRL_PLL_REF_DIV_SHIFT 26 112#define OSC_CTRL_PLL_REF_DIV_SHIFT 26
@@ -177,7 +170,6 @@ static DEFINE_SPINLOCK(pll_d_lock);
177static DEFINE_SPINLOCK(pll_d2_lock); 170static DEFINE_SPINLOCK(pll_d2_lock);
178static DEFINE_SPINLOCK(pll_u_lock); 171static DEFINE_SPINLOCK(pll_u_lock);
179static DEFINE_SPINLOCK(pll_re_lock); 172static DEFINE_SPINLOCK(pll_re_lock);
180static DEFINE_SPINLOCK(clk_out_lock);
181static DEFINE_SPINLOCK(sysrate_lock); 173static DEFINE_SPINLOCK(sysrate_lock);
182 174
183static struct div_nmp pllxc_nmp = { 175static struct div_nmp pllxc_nmp = {
@@ -1199,71 +1191,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
1199 clks[TEGRA114_CLK_PLL_E_OUT0] = clk; 1191 clks[TEGRA114_CLK_PLL_E_OUT0] = clk;
1200} 1192}
1201 1193
1202static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2",
1203 "clk_m_div4", "extern1",
1204};
1205
1206static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2",
1207 "clk_m_div4", "extern2",
1208};
1209
1210static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2",
1211 "clk_m_div4", "extern3",
1212};
1213
1214static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
1215{
1216 struct clk *clk;
1217
1218 /* clk_out_1 */
1219 clk = clk_register_mux(NULL, "clk_out_1_mux", clk_out1_parents,
1220 ARRAY_SIZE(clk_out1_parents),
1221 CLK_SET_RATE_NO_REPARENT,
1222 pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0,
1223 &clk_out_lock);
1224 clks[TEGRA114_CLK_CLK_OUT_1_MUX] = clk;
1225 clk = clk_register_gate(NULL, "clk_out_1", "clk_out_1_mux", 0,
1226 pmc_base + PMC_CLK_OUT_CNTRL, 2, 0,
1227 &clk_out_lock);
1228 clks[TEGRA114_CLK_CLK_OUT_1] = clk;
1229
1230 /* clk_out_2 */
1231 clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents,
1232 ARRAY_SIZE(clk_out2_parents),
1233 CLK_SET_RATE_NO_REPARENT,
1234 pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0,
1235 &clk_out_lock);
1236 clks[TEGRA114_CLK_CLK_OUT_2_MUX] = clk;
1237 clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0,
1238 pmc_base + PMC_CLK_OUT_CNTRL, 10, 0,
1239 &clk_out_lock);
1240 clks[TEGRA114_CLK_CLK_OUT_2] = clk;
1241
1242 /* clk_out_3 */
1243 clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents,
1244 ARRAY_SIZE(clk_out3_parents),
1245 CLK_SET_RATE_NO_REPARENT,
1246 pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0,
1247 &clk_out_lock);
1248 clks[TEGRA114_CLK_CLK_OUT_3_MUX] = clk;
1249 clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0,
1250 pmc_base + PMC_CLK_OUT_CNTRL, 18, 0,
1251 &clk_out_lock);
1252 clks[TEGRA114_CLK_CLK_OUT_3] = clk;
1253
1254 /* blink */
1255 /* clear the blink timer register to directly output clk_32k */
1256 writel_relaxed(0, pmc_base + PMC_BLINK_TIMER);
1257 clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0,
1258 pmc_base + PMC_DPD_PADS_ORIDE,
1259 PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL);
1260 clk = clk_register_gate(NULL, "blink", "blink_override", 0,
1261 pmc_base + PMC_CTRL,
1262 PMC_CTRL_BLINK_ENB, 0, NULL);
1263 clks[TEGRA114_CLK_BLINK] = clk;
1264
1265}
1266
1267static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4", 1194static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
1268 "pll_p", "pll_p_out2", "unused", 1195 "pll_p", "pll_p_out2", "unused",
1269 "clk_32k", "pll_m_out1" }; 1196 "clk_32k", "pll_m_out1" };
@@ -1612,7 +1539,7 @@ static void __init tegra114_clock_init(struct device_node *np)
1612 tegra114_pll_init(clk_base, pmc_base); 1539 tegra114_pll_init(clk_base, pmc_base);
1613 tegra114_periph_clk_init(clk_base, pmc_base); 1540 tegra114_periph_clk_init(clk_base, pmc_base);
1614 tegra_audio_clk_init(clk_base, pmc_base, tegra114_clks, &pll_a_params); 1541 tegra_audio_clk_init(clk_base, pmc_base, tegra114_clks, &pll_a_params);
1615 tegra114_pmc_clk_init(pmc_base); 1542 tegra_pmc_clk_init(pmc_base, tegra114_clks);
1616 tegra114_super_clk_init(clk_base); 1543 tegra114_super_clk_init(clk_base);
1617 1544
1618 tegra_add_of_provider(np); 1545 tegra_add_of_provider(np);
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 9ec6118e9b99..2d4881763902 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -604,6 +604,13 @@ void tegra_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base,
604 struct tegra_clk *tegra_clks, 604 struct tegra_clk *tegra_clks,
605 struct tegra_clk_pll_params *pll_params); 605 struct tegra_clk_pll_params *pll_params);
606 606
607void tegra_pmc_clk_init(void __iomem *pmc_base, struct tegra_clk *tegra_clks);
608void tegra_fixed_clk_init(struct tegra_clk *tegra_clks);
609int tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *tegra_clks,
610 unsigned long *input_freqs, int num,
611 unsigned long *osc_freq,
612 unsigned long *pll_ref_freq);
613
607void tegra114_clock_tune_cpu_trimmers_high(void); 614void tegra114_clock_tune_cpu_trimmers_high(void);
608void tegra114_clock_tune_cpu_trimmers_low(void); 615void tegra114_clock_tune_cpu_trimmers_low(void);
609void tegra114_clock_tune_cpu_trimmers_init(void); 616void tegra114_clock_tune_cpu_trimmers_init(void);