diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/tegra/Makefile | 2 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra20.c | 1273 | ||||
-rw-r--r-- | drivers/clk/tegra/clk.h | 6 |
3 files changed, 1281 insertions, 0 deletions
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile index 68bd353a2108..00484fd4e515 100644 --- a/drivers/clk/tegra/Makefile +++ b/drivers/clk/tegra/Makefile | |||
@@ -6,3 +6,5 @@ obj-y += clk-periph-gate.o | |||
6 | obj-y += clk-pll.o | 6 | obj-y += clk-pll.o |
7 | obj-y += clk-pll-out.o | 7 | obj-y += clk-pll-out.o |
8 | obj-y += clk-super.o | 8 | obj-y += clk-super.o |
9 | |||
10 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o | ||
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c new file mode 100644 index 000000000000..4ae8287b0f81 --- /dev/null +++ b/drivers/clk/tegra/clk-tegra20.c | |||
@@ -0,0 +1,1273 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012, 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/clk/tegra.h> | ||
24 | |||
25 | #include "clk.h" | ||
26 | |||
27 | #define RST_DEVICES_L 0x004 | ||
28 | #define RST_DEVICES_H 0x008 | ||
29 | #define RST_DEVICES_U 0x00c | ||
30 | #define RST_DEVICES_SET_L 0x300 | ||
31 | #define RST_DEVICES_CLR_L 0x304 | ||
32 | #define RST_DEVICES_SET_H 0x308 | ||
33 | #define RST_DEVICES_CLR_H 0x30c | ||
34 | #define RST_DEVICES_SET_U 0x310 | ||
35 | #define RST_DEVICES_CLR_U 0x314 | ||
36 | #define RST_DEVICES_NUM 3 | ||
37 | |||
38 | #define CLK_OUT_ENB_L 0x010 | ||
39 | #define CLK_OUT_ENB_H 0x014 | ||
40 | #define CLK_OUT_ENB_U 0x018 | ||
41 | #define CLK_OUT_ENB_SET_L 0x320 | ||
42 | #define CLK_OUT_ENB_CLR_L 0x324 | ||
43 | #define CLK_OUT_ENB_SET_H 0x328 | ||
44 | #define CLK_OUT_ENB_CLR_H 0x32c | ||
45 | #define CLK_OUT_ENB_SET_U 0x330 | ||
46 | #define CLK_OUT_ENB_CLR_U 0x334 | ||
47 | #define CLK_OUT_ENB_NUM 3 | ||
48 | |||
49 | #define OSC_CTRL 0x50 | ||
50 | #define OSC_CTRL_OSC_FREQ_MASK (3<<30) | ||
51 | #define OSC_CTRL_OSC_FREQ_13MHZ (0<<30) | ||
52 | #define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30) | ||
53 | #define OSC_CTRL_OSC_FREQ_12MHZ (2<<30) | ||
54 | #define OSC_CTRL_OSC_FREQ_26MHZ (3<<30) | ||
55 | #define OSC_CTRL_MASK (0x3f2 | OSC_CTRL_OSC_FREQ_MASK) | ||
56 | |||
57 | #define OSC_CTRL_PLL_REF_DIV_MASK (3<<28) | ||
58 | #define OSC_CTRL_PLL_REF_DIV_1 (0<<28) | ||
59 | #define OSC_CTRL_PLL_REF_DIV_2 (1<<28) | ||
60 | #define OSC_CTRL_PLL_REF_DIV_4 (2<<28) | ||
61 | |||
62 | #define OSC_FREQ_DET 0x58 | ||
63 | #define OSC_FREQ_DET_TRIG (1<<31) | ||
64 | |||
65 | #define OSC_FREQ_DET_STATUS 0x5c | ||
66 | #define OSC_FREQ_DET_BUSY (1<<31) | ||
67 | #define OSC_FREQ_DET_CNT_MASK 0xFFFF | ||
68 | |||
69 | #define PLLS_BASE 0xf0 | ||
70 | #define PLLS_MISC 0xf4 | ||
71 | #define PLLC_BASE 0x80 | ||
72 | #define PLLC_MISC 0x8c | ||
73 | #define PLLM_BASE 0x90 | ||
74 | #define PLLM_MISC 0x9c | ||
75 | #define PLLP_BASE 0xa0 | ||
76 | #define PLLP_MISC 0xac | ||
77 | #define PLLA_BASE 0xb0 | ||
78 | #define PLLA_MISC 0xbc | ||
79 | #define PLLU_BASE 0xc0 | ||
80 | #define PLLU_MISC 0xcc | ||
81 | #define PLLD_BASE 0xd0 | ||
82 | #define PLLD_MISC 0xdc | ||
83 | #define PLLX_BASE 0xe0 | ||
84 | #define PLLX_MISC 0xe4 | ||
85 | #define PLLE_BASE 0xe8 | ||
86 | #define PLLE_MISC 0xec | ||
87 | |||
88 | #define PLL_BASE_LOCK 27 | ||
89 | #define PLLE_MISC_LOCK 11 | ||
90 | |||
91 | #define PLL_MISC_LOCK_ENABLE 18 | ||
92 | #define PLLDU_MISC_LOCK_ENABLE 22 | ||
93 | #define PLLE_MISC_LOCK_ENABLE 9 | ||
94 | |||
95 | #define PLLC_OUT 0x84 | ||
96 | #define PLLM_OUT 0x94 | ||
97 | #define PLLP_OUTA 0xa4 | ||
98 | #define PLLP_OUTB 0xa8 | ||
99 | #define PLLA_OUT 0xb4 | ||
100 | |||
101 | #define CCLK_BURST_POLICY 0x20 | ||
102 | #define SUPER_CCLK_DIVIDER 0x24 | ||
103 | #define SCLK_BURST_POLICY 0x28 | ||
104 | #define SUPER_SCLK_DIVIDER 0x2c | ||
105 | #define CLK_SYSTEM_RATE 0x30 | ||
106 | |||
107 | #define CLK_SOURCE_I2S1 0x100 | ||
108 | #define CLK_SOURCE_I2S2 0x104 | ||
109 | #define CLK_SOURCE_SPDIF_OUT 0x108 | ||
110 | #define CLK_SOURCE_SPDIF_IN 0x10c | ||
111 | #define CLK_SOURCE_PWM 0x110 | ||
112 | #define CLK_SOURCE_SPI 0x114 | ||
113 | #define CLK_SOURCE_SBC1 0x134 | ||
114 | #define CLK_SOURCE_SBC2 0x118 | ||
115 | #define CLK_SOURCE_SBC3 0x11c | ||
116 | #define CLK_SOURCE_SBC4 0x1b4 | ||
117 | #define CLK_SOURCE_XIO 0x120 | ||
118 | #define CLK_SOURCE_TWC 0x12c | ||
119 | #define CLK_SOURCE_IDE 0x144 | ||
120 | #define CLK_SOURCE_NDFLASH 0x160 | ||
121 | #define CLK_SOURCE_VFIR 0x168 | ||
122 | #define CLK_SOURCE_SDMMC1 0x150 | ||
123 | #define CLK_SOURCE_SDMMC2 0x154 | ||
124 | #define CLK_SOURCE_SDMMC3 0x1bc | ||
125 | #define CLK_SOURCE_SDMMC4 0x164 | ||
126 | #define CLK_SOURCE_CVE 0x140 | ||
127 | #define CLK_SOURCE_TVO 0x188 | ||
128 | #define CLK_SOURCE_TVDAC 0x194 | ||
129 | #define CLK_SOURCE_HDMI 0x18c | ||
130 | #define CLK_SOURCE_DISP1 0x138 | ||
131 | #define CLK_SOURCE_DISP2 0x13c | ||
132 | #define CLK_SOURCE_CSITE 0x1d4 | ||
133 | #define CLK_SOURCE_LA 0x1f8 | ||
134 | #define CLK_SOURCE_OWR 0x1cc | ||
135 | #define CLK_SOURCE_NOR 0x1d0 | ||
136 | #define CLK_SOURCE_MIPI 0x174 | ||
137 | #define CLK_SOURCE_I2C1 0x124 | ||
138 | #define CLK_SOURCE_I2C2 0x198 | ||
139 | #define CLK_SOURCE_I2C3 0x1b8 | ||
140 | #define CLK_SOURCE_DVC 0x128 | ||
141 | #define CLK_SOURCE_UARTA 0x178 | ||
142 | #define CLK_SOURCE_UARTB 0x17c | ||
143 | #define CLK_SOURCE_UARTC 0x1a0 | ||
144 | #define CLK_SOURCE_UARTD 0x1c0 | ||
145 | #define CLK_SOURCE_UARTE 0x1c4 | ||
146 | #define CLK_SOURCE_3D 0x158 | ||
147 | #define CLK_SOURCE_2D 0x15c | ||
148 | #define CLK_SOURCE_MPE 0x170 | ||
149 | #define CLK_SOURCE_EPP 0x16c | ||
150 | #define CLK_SOURCE_HOST1X 0x180 | ||
151 | #define CLK_SOURCE_VDE 0x1c8 | ||
152 | #define CLK_SOURCE_VI 0x148 | ||
153 | #define CLK_SOURCE_VI_SENSOR 0x1a8 | ||
154 | #define CLK_SOURCE_EMC 0x19c | ||
155 | |||
156 | #define AUDIO_SYNC_CLK 0x38 | ||
157 | |||
158 | #define PMC_CTRL 0x0 | ||
159 | #define PMC_CTRL_BLINK_ENB 7 | ||
160 | #define PMC_DPD_PADS_ORIDE 0x1c | ||
161 | #define PMC_DPD_PADS_ORIDE_BLINK_ENB 20 | ||
162 | #define PMC_BLINK_TIMER 0x40 | ||
163 | |||
164 | /* Tegra CPU clock and reset control regs */ | ||
165 | #define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX 0x4c | ||
166 | #define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET 0x340 | ||
167 | #define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR 0x344 | ||
168 | |||
169 | #define CPU_CLOCK(cpu) (0x1 << (8 + cpu)) | ||
170 | #define CPU_RESET(cpu) (0x1111ul << (cpu)) | ||
171 | |||
172 | static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM * 32]; | ||
173 | |||
174 | static void __iomem *clk_base; | ||
175 | static void __iomem *pmc_base; | ||
176 | |||
177 | static DEFINE_SPINLOCK(pll_div_lock); | ||
178 | |||
179 | #define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset, \ | ||
180 | _clk_num, _regs, _gate_flags, _clk_id) \ | ||
181 | TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ | ||
182 | 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ | ||
183 | _regs, _clk_num, periph_clk_enb_refcnt, \ | ||
184 | _gate_flags, _clk_id) | ||
185 | |||
186 | #define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset, \ | ||
187 | _clk_num, _regs, _gate_flags, _clk_id) \ | ||
188 | TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ | ||
189 | 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs, \ | ||
190 | _clk_num, periph_clk_enb_refcnt, _gate_flags, \ | ||
191 | _clk_id) | ||
192 | |||
193 | #define TEGRA_INIT_DATA_DIV16(_name, _con_id, _dev_id, _parents, _offset, \ | ||
194 | _clk_num, _regs, _gate_flags, _clk_id) \ | ||
195 | TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ | ||
196 | 30, 2, 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP, _regs, \ | ||
197 | _clk_num, periph_clk_enb_refcnt, _gate_flags, \ | ||
198 | _clk_id) | ||
199 | |||
200 | #define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \ | ||
201 | _mux_shift, _mux_width, _clk_num, _regs, \ | ||
202 | _gate_flags, _clk_id) \ | ||
203 | TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ | ||
204 | _mux_shift, _mux_width, 0, 0, 0, 0, 0, _regs, \ | ||
205 | _clk_num, periph_clk_enb_refcnt, _gate_flags, \ | ||
206 | _clk_id) | ||
207 | |||
208 | /* IDs assigned here must be in sync with DT bindings definition | ||
209 | * for Tegra20 clocks . | ||
210 | */ | ||
211 | enum tegra20_clk { | ||
212 | cpu, ac97 = 3, rtc, timer, uarta, gpio = 8, sdmmc2, i2s1 = 11, i2c1, | ||
213 | ndflash, sdmmc1, sdmmc4, twc, pwm, i2s2, epp, gr2d = 21, usbd, isp, | ||
214 | gr3d, ide, disp2, disp1, host1x, vcp, cache2 = 31, mem, ahbdma, apbdma, | ||
215 | kbc = 36, stat_mon, pmc, fuse, kfuse, sbc1, nor, spi, sbc2, xio, sbc3, | ||
216 | dvc, dsi, mipi = 50, hdmi, csi, tvdac, i2c2, uartc, emc = 57, usb2, | ||
217 | usb3, mpe, vde, bsea, bsev, speedo, uartd, uarte, i2c3, sbc4, sdmmc3, | ||
218 | pex, owr, afi, csite, pcie_xclk, avpucq = 75, la, irama = 84, iramb, | ||
219 | iramc, iramd, cram2, audio_2x, clk_d, csus = 92, cdev1, cdev2, | ||
220 | uartb = 96, vfir, spdif_in, spdif_out, vi, vi_sensor, tvo, cve, | ||
221 | osc, clk_32k, clk_m, sclk, cclk, hclk, pclk, blink, pll_a, pll_a_out0, | ||
222 | pll_c, pll_c_out1, pll_d, pll_d_out0, pll_e, pll_m, pll_m_out1, | ||
223 | pll_p, pll_p_out1, pll_p_out2, pll_p_out3, pll_p_out4, pll_u, | ||
224 | pll_x, audio, pll_ref, twd, clk_max, | ||
225 | }; | ||
226 | |||
227 | static struct clk *clks[clk_max]; | ||
228 | static struct clk_onecell_data clk_data; | ||
229 | |||
230 | static struct tegra_clk_pll_freq_table pll_c_freq_table[] = { | ||
231 | { 12000000, 600000000, 600, 12, 1, 8 }, | ||
232 | { 13000000, 600000000, 600, 13, 1, 8 }, | ||
233 | { 19200000, 600000000, 500, 16, 1, 6 }, | ||
234 | { 26000000, 600000000, 600, 26, 1, 8 }, | ||
235 | { 0, 0, 0, 0, 0, 0 }, | ||
236 | }; | ||
237 | |||
238 | static struct tegra_clk_pll_freq_table pll_m_freq_table[] = { | ||
239 | { 12000000, 666000000, 666, 12, 1, 8}, | ||
240 | { 13000000, 666000000, 666, 13, 1, 8}, | ||
241 | { 19200000, 666000000, 555, 16, 1, 8}, | ||
242 | { 26000000, 666000000, 666, 26, 1, 8}, | ||
243 | { 12000000, 600000000, 600, 12, 1, 8}, | ||
244 | { 13000000, 600000000, 600, 13, 1, 8}, | ||
245 | { 19200000, 600000000, 375, 12, 1, 6}, | ||
246 | { 26000000, 600000000, 600, 26, 1, 8}, | ||
247 | { 0, 0, 0, 0, 0, 0 }, | ||
248 | }; | ||
249 | |||
250 | static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { | ||
251 | { 12000000, 216000000, 432, 12, 2, 8}, | ||
252 | { 13000000, 216000000, 432, 13, 2, 8}, | ||
253 | { 19200000, 216000000, 90, 4, 2, 1}, | ||
254 | { 26000000, 216000000, 432, 26, 2, 8}, | ||
255 | { 12000000, 432000000, 432, 12, 1, 8}, | ||
256 | { 13000000, 432000000, 432, 13, 1, 8}, | ||
257 | { 19200000, 432000000, 90, 4, 1, 1}, | ||
258 | { 26000000, 432000000, 432, 26, 1, 8}, | ||
259 | { 0, 0, 0, 0, 0, 0 }, | ||
260 | }; | ||
261 | |||
262 | static struct tegra_clk_pll_freq_table pll_a_freq_table[] = { | ||
263 | { 28800000, 56448000, 49, 25, 1, 1}, | ||
264 | { 28800000, 73728000, 64, 25, 1, 1}, | ||
265 | { 28800000, 24000000, 5, 6, 1, 1}, | ||
266 | { 0, 0, 0, 0, 0, 0 }, | ||
267 | }; | ||
268 | |||
269 | static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { | ||
270 | { 12000000, 216000000, 216, 12, 1, 4}, | ||
271 | { 13000000, 216000000, 216, 13, 1, 4}, | ||
272 | { 19200000, 216000000, 135, 12, 1, 3}, | ||
273 | { 26000000, 216000000, 216, 26, 1, 4}, | ||
274 | |||
275 | { 12000000, 594000000, 594, 12, 1, 8}, | ||
276 | { 13000000, 594000000, 594, 13, 1, 8}, | ||
277 | { 19200000, 594000000, 495, 16, 1, 8}, | ||
278 | { 26000000, 594000000, 594, 26, 1, 8}, | ||
279 | |||
280 | { 12000000, 1000000000, 1000, 12, 1, 12}, | ||
281 | { 13000000, 1000000000, 1000, 13, 1, 12}, | ||
282 | { 19200000, 1000000000, 625, 12, 1, 8}, | ||
283 | { 26000000, 1000000000, 1000, 26, 1, 12}, | ||
284 | |||
285 | { 0, 0, 0, 0, 0, 0 }, | ||
286 | }; | ||
287 | |||
288 | static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { | ||
289 | { 12000000, 480000000, 960, 12, 2, 0}, | ||
290 | { 13000000, 480000000, 960, 13, 2, 0}, | ||
291 | { 19200000, 480000000, 200, 4, 2, 0}, | ||
292 | { 26000000, 480000000, 960, 26, 2, 0}, | ||
293 | { 0, 0, 0, 0, 0, 0 }, | ||
294 | }; | ||
295 | |||
296 | static struct tegra_clk_pll_freq_table pll_x_freq_table[] = { | ||
297 | /* 1 GHz */ | ||
298 | { 12000000, 1000000000, 1000, 12, 1, 12}, | ||
299 | { 13000000, 1000000000, 1000, 13, 1, 12}, | ||
300 | { 19200000, 1000000000, 625, 12, 1, 8}, | ||
301 | { 26000000, 1000000000, 1000, 26, 1, 12}, | ||
302 | |||
303 | /* 912 MHz */ | ||
304 | { 12000000, 912000000, 912, 12, 1, 12}, | ||
305 | { 13000000, 912000000, 912, 13, 1, 12}, | ||
306 | { 19200000, 912000000, 760, 16, 1, 8}, | ||
307 | { 26000000, 912000000, 912, 26, 1, 12}, | ||
308 | |||
309 | /* 816 MHz */ | ||
310 | { 12000000, 816000000, 816, 12, 1, 12}, | ||
311 | { 13000000, 816000000, 816, 13, 1, 12}, | ||
312 | { 19200000, 816000000, 680, 16, 1, 8}, | ||
313 | { 26000000, 816000000, 816, 26, 1, 12}, | ||
314 | |||
315 | /* 760 MHz */ | ||
316 | { 12000000, 760000000, 760, 12, 1, 12}, | ||
317 | { 13000000, 760000000, 760, 13, 1, 12}, | ||
318 | { 19200000, 760000000, 950, 24, 1, 8}, | ||
319 | { 26000000, 760000000, 760, 26, 1, 12}, | ||
320 | |||
321 | /* 750 MHz */ | ||
322 | { 12000000, 750000000, 750, 12, 1, 12}, | ||
323 | { 13000000, 750000000, 750, 13, 1, 12}, | ||
324 | { 19200000, 750000000, 625, 16, 1, 8}, | ||
325 | { 26000000, 750000000, 750, 26, 1, 12}, | ||
326 | |||
327 | /* 608 MHz */ | ||
328 | { 12000000, 608000000, 608, 12, 1, 12}, | ||
329 | { 13000000, 608000000, 608, 13, 1, 12}, | ||
330 | { 19200000, 608000000, 380, 12, 1, 8}, | ||
331 | { 26000000, 608000000, 608, 26, 1, 12}, | ||
332 | |||
333 | /* 456 MHz */ | ||
334 | { 12000000, 456000000, 456, 12, 1, 12}, | ||
335 | { 13000000, 456000000, 456, 13, 1, 12}, | ||
336 | { 19200000, 456000000, 380, 16, 1, 8}, | ||
337 | { 26000000, 456000000, 456, 26, 1, 12}, | ||
338 | |||
339 | /* 312 MHz */ | ||
340 | { 12000000, 312000000, 312, 12, 1, 12}, | ||
341 | { 13000000, 312000000, 312, 13, 1, 12}, | ||
342 | { 19200000, 312000000, 260, 16, 1, 8}, | ||
343 | { 26000000, 312000000, 312, 26, 1, 12}, | ||
344 | |||
345 | { 0, 0, 0, 0, 0, 0 }, | ||
346 | }; | ||
347 | |||
348 | static struct tegra_clk_pll_freq_table pll_e_freq_table[] = { | ||
349 | { 12000000, 100000000, 200, 24, 1, 0 }, | ||
350 | { 0, 0, 0, 0, 0, 0 }, | ||
351 | }; | ||
352 | |||
353 | /* PLL parameters */ | ||
354 | static struct tegra_clk_pll_params pll_c_params = { | ||
355 | .input_min = 2000000, | ||
356 | .input_max = 31000000, | ||
357 | .cf_min = 1000000, | ||
358 | .cf_max = 6000000, | ||
359 | .vco_min = 20000000, | ||
360 | .vco_max = 1400000000, | ||
361 | .base_reg = PLLC_BASE, | ||
362 | .misc_reg = PLLC_MISC, | ||
363 | .lock_bit_idx = PLL_BASE_LOCK, | ||
364 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | ||
365 | .lock_delay = 300, | ||
366 | }; | ||
367 | |||
368 | static struct tegra_clk_pll_params pll_m_params = { | ||
369 | .input_min = 2000000, | ||
370 | .input_max = 31000000, | ||
371 | .cf_min = 1000000, | ||
372 | .cf_max = 6000000, | ||
373 | .vco_min = 20000000, | ||
374 | .vco_max = 1200000000, | ||
375 | .base_reg = PLLM_BASE, | ||
376 | .misc_reg = PLLM_MISC, | ||
377 | .lock_bit_idx = PLL_BASE_LOCK, | ||
378 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | ||
379 | .lock_delay = 300, | ||
380 | }; | ||
381 | |||
382 | static struct tegra_clk_pll_params pll_p_params = { | ||
383 | .input_min = 2000000, | ||
384 | .input_max = 31000000, | ||
385 | .cf_min = 1000000, | ||
386 | .cf_max = 6000000, | ||
387 | .vco_min = 20000000, | ||
388 | .vco_max = 1400000000, | ||
389 | .base_reg = PLLP_BASE, | ||
390 | .misc_reg = PLLP_MISC, | ||
391 | .lock_bit_idx = PLL_BASE_LOCK, | ||
392 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | ||
393 | .lock_delay = 300, | ||
394 | }; | ||
395 | |||
396 | static struct tegra_clk_pll_params pll_a_params = { | ||
397 | .input_min = 2000000, | ||
398 | .input_max = 31000000, | ||
399 | .cf_min = 1000000, | ||
400 | .cf_max = 6000000, | ||
401 | .vco_min = 20000000, | ||
402 | .vco_max = 1400000000, | ||
403 | .base_reg = PLLA_BASE, | ||
404 | .misc_reg = PLLA_MISC, | ||
405 | .lock_bit_idx = PLL_BASE_LOCK, | ||
406 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | ||
407 | .lock_delay = 300, | ||
408 | }; | ||
409 | |||
410 | static struct tegra_clk_pll_params pll_d_params = { | ||
411 | .input_min = 2000000, | ||
412 | .input_max = 40000000, | ||
413 | .cf_min = 1000000, | ||
414 | .cf_max = 6000000, | ||
415 | .vco_min = 40000000, | ||
416 | .vco_max = 1000000000, | ||
417 | .base_reg = PLLD_BASE, | ||
418 | .misc_reg = PLLD_MISC, | ||
419 | .lock_bit_idx = PLL_BASE_LOCK, | ||
420 | .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, | ||
421 | .lock_delay = 1000, | ||
422 | }; | ||
423 | |||
424 | static struct tegra_clk_pll_params pll_u_params = { | ||
425 | .input_min = 2000000, | ||
426 | .input_max = 40000000, | ||
427 | .cf_min = 1000000, | ||
428 | .cf_max = 6000000, | ||
429 | .vco_min = 48000000, | ||
430 | .vco_max = 960000000, | ||
431 | .base_reg = PLLU_BASE, | ||
432 | .misc_reg = PLLU_MISC, | ||
433 | .lock_bit_idx = PLL_BASE_LOCK, | ||
434 | .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, | ||
435 | .lock_delay = 1000, | ||
436 | }; | ||
437 | |||
438 | static struct tegra_clk_pll_params pll_x_params = { | ||
439 | .input_min = 2000000, | ||
440 | .input_max = 31000000, | ||
441 | .cf_min = 1000000, | ||
442 | .cf_max = 6000000, | ||
443 | .vco_min = 20000000, | ||
444 | .vco_max = 1200000000, | ||
445 | .base_reg = PLLX_BASE, | ||
446 | .misc_reg = PLLX_MISC, | ||
447 | .lock_bit_idx = PLL_BASE_LOCK, | ||
448 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | ||
449 | .lock_delay = 300, | ||
450 | }; | ||
451 | |||
452 | static struct tegra_clk_pll_params pll_e_params = { | ||
453 | .input_min = 12000000, | ||
454 | .input_max = 12000000, | ||
455 | .cf_min = 0, | ||
456 | .cf_max = 0, | ||
457 | .vco_min = 0, | ||
458 | .vco_max = 0, | ||
459 | .base_reg = PLLE_BASE, | ||
460 | .misc_reg = PLLE_MISC, | ||
461 | .lock_bit_idx = PLLE_MISC_LOCK, | ||
462 | .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE, | ||
463 | .lock_delay = 0, | ||
464 | }; | ||
465 | |||
466 | /* Peripheral clock registers */ | ||
467 | static struct tegra_clk_periph_regs periph_l_regs = { | ||
468 | .enb_reg = CLK_OUT_ENB_L, | ||
469 | .enb_set_reg = CLK_OUT_ENB_SET_L, | ||
470 | .enb_clr_reg = CLK_OUT_ENB_CLR_L, | ||
471 | .rst_reg = RST_DEVICES_L, | ||
472 | .rst_set_reg = RST_DEVICES_SET_L, | ||
473 | .rst_clr_reg = RST_DEVICES_CLR_L, | ||
474 | }; | ||
475 | |||
476 | static struct tegra_clk_periph_regs periph_h_regs = { | ||
477 | .enb_reg = CLK_OUT_ENB_H, | ||
478 | .enb_set_reg = CLK_OUT_ENB_SET_H, | ||
479 | .enb_clr_reg = CLK_OUT_ENB_CLR_H, | ||
480 | .rst_reg = RST_DEVICES_H, | ||
481 | .rst_set_reg = RST_DEVICES_SET_H, | ||
482 | .rst_clr_reg = RST_DEVICES_CLR_H, | ||
483 | }; | ||
484 | |||
485 | static struct tegra_clk_periph_regs periph_u_regs = { | ||
486 | .enb_reg = CLK_OUT_ENB_U, | ||
487 | .enb_set_reg = CLK_OUT_ENB_SET_U, | ||
488 | .enb_clr_reg = CLK_OUT_ENB_CLR_U, | ||
489 | .rst_reg = RST_DEVICES_U, | ||
490 | .rst_set_reg = RST_DEVICES_SET_U, | ||
491 | .rst_clr_reg = RST_DEVICES_CLR_U, | ||
492 | }; | ||
493 | |||
494 | static unsigned long tegra20_clk_measure_input_freq(void) | ||
495 | { | ||
496 | u32 osc_ctrl = readl_relaxed(clk_base + OSC_CTRL); | ||
497 | u32 auto_clk_control = osc_ctrl & OSC_CTRL_OSC_FREQ_MASK; | ||
498 | u32 pll_ref_div = osc_ctrl & OSC_CTRL_PLL_REF_DIV_MASK; | ||
499 | unsigned long input_freq; | ||
500 | |||
501 | switch (auto_clk_control) { | ||
502 | case OSC_CTRL_OSC_FREQ_12MHZ: | ||
503 | BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); | ||
504 | input_freq = 12000000; | ||
505 | break; | ||
506 | case OSC_CTRL_OSC_FREQ_13MHZ: | ||
507 | BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); | ||
508 | input_freq = 13000000; | ||
509 | break; | ||
510 | case OSC_CTRL_OSC_FREQ_19_2MHZ: | ||
511 | BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); | ||
512 | input_freq = 19200000; | ||
513 | break; | ||
514 | case OSC_CTRL_OSC_FREQ_26MHZ: | ||
515 | BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1); | ||
516 | input_freq = 26000000; | ||
517 | break; | ||
518 | default: | ||
519 | pr_err("Unexpected clock autodetect value %d", | ||
520 | auto_clk_control); | ||
521 | BUG(); | ||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | return input_freq; | ||
526 | } | ||
527 | |||
528 | static unsigned int tegra20_get_pll_ref_div(void) | ||
529 | { | ||
530 | u32 pll_ref_div = readl_relaxed(clk_base + OSC_CTRL) & | ||
531 | OSC_CTRL_PLL_REF_DIV_MASK; | ||
532 | |||
533 | switch (pll_ref_div) { | ||
534 | case OSC_CTRL_PLL_REF_DIV_1: | ||
535 | return 1; | ||
536 | case OSC_CTRL_PLL_REF_DIV_2: | ||
537 | return 2; | ||
538 | case OSC_CTRL_PLL_REF_DIV_4: | ||
539 | return 4; | ||
540 | default: | ||
541 | pr_err("Invalied pll ref divider %d\n", pll_ref_div); | ||
542 | BUG(); | ||
543 | } | ||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | static void tegra20_pll_init(void) | ||
548 | { | ||
549 | struct clk *clk; | ||
550 | |||
551 | /* PLLC */ | ||
552 | clk = tegra_clk_register_pll("pll_c", "pll_ref", clk_base, NULL, 0, | ||
553 | 0, &pll_c_params, TEGRA_PLL_HAS_CPCON, | ||
554 | pll_c_freq_table, NULL); | ||
555 | clk_register_clkdev(clk, "pll_c", NULL); | ||
556 | clks[pll_c] = clk; | ||
557 | |||
558 | /* PLLC_OUT1 */ | ||
559 | clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c", | ||
560 | clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP, | ||
561 | 8, 8, 1, NULL); | ||
562 | clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div", | ||
563 | clk_base + PLLC_OUT, 1, 0, CLK_SET_RATE_PARENT, | ||
564 | 0, NULL); | ||
565 | clk_register_clkdev(clk, "pll_c_out1", NULL); | ||
566 | clks[pll_c_out1] = clk; | ||
567 | |||
568 | /* PLLP */ | ||
569 | clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, NULL, 0, | ||
570 | 216000000, &pll_p_params, TEGRA_PLL_FIXED | | ||
571 | TEGRA_PLL_HAS_CPCON, pll_p_freq_table, NULL); | ||
572 | clk_register_clkdev(clk, "pll_p", NULL); | ||
573 | clks[pll_p] = clk; | ||
574 | |||
575 | /* PLLP_OUT1 */ | ||
576 | clk = tegra_clk_register_divider("pll_p_out1_div", "pll_p", | ||
577 | clk_base + PLLP_OUTA, 0, | ||
578 | TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP, | ||
579 | 8, 8, 1, &pll_div_lock); | ||
580 | clk = tegra_clk_register_pll_out("pll_p_out1", "pll_p_out1_div", | ||
581 | clk_base + PLLP_OUTA, 1, 0, | ||
582 | CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, | ||
583 | &pll_div_lock); | ||
584 | clk_register_clkdev(clk, "pll_p_out1", NULL); | ||
585 | clks[pll_p_out1] = clk; | ||
586 | |||
587 | /* PLLP_OUT2 */ | ||
588 | clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p", | ||
589 | clk_base + PLLP_OUTA, 0, | ||
590 | TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP, | ||
591 | 24, 8, 1, &pll_div_lock); | ||
592 | clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div", | ||
593 | clk_base + PLLP_OUTA, 17, 16, | ||
594 | CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, | ||
595 | &pll_div_lock); | ||
596 | clk_register_clkdev(clk, "pll_p_out2", NULL); | ||
597 | clks[pll_p_out2] = clk; | ||
598 | |||
599 | /* PLLP_OUT3 */ | ||
600 | clk = tegra_clk_register_divider("pll_p_out3_div", "pll_p", | ||
601 | clk_base + PLLP_OUTB, 0, | ||
602 | TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP, | ||
603 | 8, 8, 1, &pll_div_lock); | ||
604 | clk = tegra_clk_register_pll_out("pll_p_out3", "pll_p_out3_div", | ||
605 | clk_base + PLLP_OUTB, 1, 0, | ||
606 | CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, | ||
607 | &pll_div_lock); | ||
608 | clk_register_clkdev(clk, "pll_p_out3", NULL); | ||
609 | clks[pll_p_out3] = clk; | ||
610 | |||
611 | /* PLLP_OUT4 */ | ||
612 | clk = tegra_clk_register_divider("pll_p_out4_div", "pll_p", | ||
613 | clk_base + PLLP_OUTB, 0, | ||
614 | TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP, | ||
615 | 24, 8, 1, &pll_div_lock); | ||
616 | clk = tegra_clk_register_pll_out("pll_p_out4", "pll_p_out4_div", | ||
617 | clk_base + PLLP_OUTB, 17, 16, | ||
618 | CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, | ||
619 | &pll_div_lock); | ||
620 | clk_register_clkdev(clk, "pll_p_out4", NULL); | ||
621 | clks[pll_p_out4] = clk; | ||
622 | |||
623 | /* PLLM */ | ||
624 | clk = tegra_clk_register_pll("pll_m", "pll_ref", clk_base, NULL, | ||
625 | CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0, | ||
626 | &pll_m_params, TEGRA_PLL_HAS_CPCON, | ||
627 | pll_m_freq_table, NULL); | ||
628 | clk_register_clkdev(clk, "pll_m", NULL); | ||
629 | clks[pll_m] = clk; | ||
630 | |||
631 | /* PLLM_OUT1 */ | ||
632 | clk = tegra_clk_register_divider("pll_m_out1_div", "pll_m", | ||
633 | clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP, | ||
634 | 8, 8, 1, NULL); | ||
635 | clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div", | ||
636 | clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED | | ||
637 | CLK_SET_RATE_PARENT, 0, NULL); | ||
638 | clk_register_clkdev(clk, "pll_m_out1", NULL); | ||
639 | clks[pll_m_out1] = clk; | ||
640 | |||
641 | /* PLLX */ | ||
642 | clk = tegra_clk_register_pll("pll_x", "pll_ref", clk_base, NULL, 0, | ||
643 | 0, &pll_x_params, TEGRA_PLL_HAS_CPCON, | ||
644 | pll_x_freq_table, NULL); | ||
645 | clk_register_clkdev(clk, "pll_x", NULL); | ||
646 | clks[pll_x] = clk; | ||
647 | |||
648 | /* PLLU */ | ||
649 | clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, NULL, 0, | ||
650 | 0, &pll_u_params, TEGRA_PLLU | TEGRA_PLL_HAS_CPCON, | ||
651 | pll_u_freq_table, NULL); | ||
652 | clk_register_clkdev(clk, "pll_u", NULL); | ||
653 | clks[pll_u] = clk; | ||
654 | |||
655 | /* PLLD */ | ||
656 | clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, NULL, 0, | ||
657 | 0, &pll_d_params, TEGRA_PLL_HAS_CPCON, | ||
658 | pll_d_freq_table, NULL); | ||
659 | clk_register_clkdev(clk, "pll_d", NULL); | ||
660 | clks[pll_d] = clk; | ||
661 | |||
662 | /* PLLD_OUT0 */ | ||
663 | clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d", | ||
664 | CLK_SET_RATE_PARENT, 1, 2); | ||
665 | clk_register_clkdev(clk, "pll_d_out0", NULL); | ||
666 | clks[pll_d_out0] = clk; | ||
667 | |||
668 | /* PLLA */ | ||
669 | clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, NULL, 0, | ||
670 | 0, &pll_a_params, TEGRA_PLL_HAS_CPCON, | ||
671 | pll_a_freq_table, NULL); | ||
672 | clk_register_clkdev(clk, "pll_a", NULL); | ||
673 | clks[pll_a] = clk; | ||
674 | |||
675 | /* PLLA_OUT0 */ | ||
676 | clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a", | ||
677 | clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP, | ||
678 | 8, 8, 1, NULL); | ||
679 | clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div", | ||
680 | clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED | | ||
681 | CLK_SET_RATE_PARENT, 0, NULL); | ||
682 | clk_register_clkdev(clk, "pll_a_out0", NULL); | ||
683 | clks[pll_a_out0] = clk; | ||
684 | |||
685 | /* PLLE */ | ||
686 | clk = tegra_clk_register_plle("pll_e", "pll_ref", clk_base, NULL, | ||
687 | 0, 100000000, &pll_e_params, | ||
688 | 0, pll_e_freq_table, NULL); | ||
689 | clk_register_clkdev(clk, "pll_e", NULL); | ||
690 | clks[pll_e] = clk; | ||
691 | } | ||
692 | |||
693 | static const char *cclk_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", | ||
694 | "pll_p_cclk", "pll_p_out4_cclk", | ||
695 | "pll_p_out3_cclk", "clk_d", "pll_x" }; | ||
696 | static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4", | ||
697 | "pll_p_out3", "pll_p_out2", "clk_d", | ||
698 | "clk_32k", "pll_m_out1" }; | ||
699 | |||
700 | static void tegra20_super_clk_init(void) | ||
701 | { | ||
702 | struct clk *clk; | ||
703 | |||
704 | /* | ||
705 | * DIV_U71 dividers for CCLK, these dividers are used only | ||
706 | * if parent clock is fixed rate. | ||
707 | */ | ||
708 | |||
709 | /* | ||
710 | * Clock input to cclk divided from pll_p using | ||
711 | * U71 divider of cclk. | ||
712 | */ | ||
713 | clk = tegra_clk_register_divider("pll_p_cclk", "pll_p", | ||
714 | clk_base + SUPER_CCLK_DIVIDER, 0, | ||
715 | TEGRA_DIVIDER_INT, 16, 8, 1, NULL); | ||
716 | clk_register_clkdev(clk, "pll_p_cclk", NULL); | ||
717 | |||
718 | /* | ||
719 | * Clock input to cclk divided from pll_p_out3 using | ||
720 | * U71 divider of cclk. | ||
721 | */ | ||
722 | clk = tegra_clk_register_divider("pll_p_out3_cclk", "pll_p_out3", | ||
723 | clk_base + SUPER_CCLK_DIVIDER, 0, | ||
724 | TEGRA_DIVIDER_INT, 16, 8, 1, NULL); | ||
725 | clk_register_clkdev(clk, "pll_p_out3_cclk", NULL); | ||
726 | |||
727 | /* | ||
728 | * Clock input to cclk divided from pll_p_out4 using | ||
729 | * U71 divider of cclk. | ||
730 | */ | ||
731 | clk = tegra_clk_register_divider("pll_p_out4_cclk", "pll_p_out4", | ||
732 | clk_base + SUPER_CCLK_DIVIDER, 0, | ||
733 | TEGRA_DIVIDER_INT, 16, 8, 1, NULL); | ||
734 | clk_register_clkdev(clk, "pll_p_out4_cclk", NULL); | ||
735 | |||
736 | /* CCLK */ | ||
737 | clk = tegra_clk_register_super_mux("cclk", cclk_parents, | ||
738 | ARRAY_SIZE(cclk_parents), CLK_SET_RATE_PARENT, | ||
739 | clk_base + CCLK_BURST_POLICY, 0, 4, 0, 0, NULL); | ||
740 | clk_register_clkdev(clk, "cclk", NULL); | ||
741 | clks[cclk] = clk; | ||
742 | |||
743 | /* SCLK */ | ||
744 | clk = tegra_clk_register_super_mux("sclk", sclk_parents, | ||
745 | ARRAY_SIZE(sclk_parents), CLK_SET_RATE_PARENT, | ||
746 | clk_base + SCLK_BURST_POLICY, 0, 4, 0, 0, NULL); | ||
747 | clk_register_clkdev(clk, "sclk", NULL); | ||
748 | clks[sclk] = clk; | ||
749 | |||
750 | /* HCLK */ | ||
751 | clk = clk_register_divider(NULL, "hclk_div", "sclk", 0, | ||
752 | clk_base + CLK_SYSTEM_RATE, 4, 2, 0, NULL); | ||
753 | clk = clk_register_gate(NULL, "hclk", "hclk_div", CLK_SET_RATE_PARENT, | ||
754 | clk_base + CLK_SYSTEM_RATE, 7, | ||
755 | CLK_GATE_SET_TO_DISABLE, NULL); | ||
756 | clk_register_clkdev(clk, "hclk", NULL); | ||
757 | clks[hclk] = clk; | ||
758 | |||
759 | /* PCLK */ | ||
760 | clk = clk_register_divider(NULL, "pclk_div", "hclk", 0, | ||
761 | clk_base + CLK_SYSTEM_RATE, 0, 2, 0, NULL); | ||
762 | clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT, | ||
763 | clk_base + CLK_SYSTEM_RATE, 3, | ||
764 | CLK_GATE_SET_TO_DISABLE, NULL); | ||
765 | clk_register_clkdev(clk, "pclk", NULL); | ||
766 | clks[pclk] = clk; | ||
767 | |||
768 | /* twd */ | ||
769 | clk = clk_register_fixed_factor(NULL, "twd", "cclk", 0, 1, 4); | ||
770 | clk_register_clkdev(clk, "twd", NULL); | ||
771 | clks[twd] = clk; | ||
772 | } | ||
773 | |||
774 | static const char *audio_parents[] = {"spdif_in", "i2s1", "i2s2", "unused", | ||
775 | "pll_a_out0", "unused", "unused", | ||
776 | "unused"}; | ||
777 | |||
778 | static void __init tegra20_audio_clk_init(void) | ||
779 | { | ||
780 | struct clk *clk; | ||
781 | |||
782 | /* audio */ | ||
783 | clk = clk_register_mux(NULL, "audio_mux", audio_parents, | ||
784 | ARRAY_SIZE(audio_parents), 0, | ||
785 | clk_base + AUDIO_SYNC_CLK, 0, 3, 0, NULL); | ||
786 | clk = clk_register_gate(NULL, "audio", "audio_mux", 0, | ||
787 | clk_base + AUDIO_SYNC_CLK, 4, | ||
788 | CLK_GATE_SET_TO_DISABLE, NULL); | ||
789 | clk_register_clkdev(clk, "audio", NULL); | ||
790 | clks[audio] = clk; | ||
791 | |||
792 | /* audio_2x */ | ||
793 | clk = clk_register_fixed_factor(NULL, "audio_doubler", "audio", | ||
794 | CLK_SET_RATE_PARENT, 2, 1); | ||
795 | clk = tegra_clk_register_periph_gate("audio_2x", "audio_doubler", | ||
796 | TEGRA_PERIPH_NO_RESET, clk_base, | ||
797 | CLK_SET_RATE_PARENT, 89, &periph_u_regs, | ||
798 | periph_clk_enb_refcnt); | ||
799 | clk_register_clkdev(clk, "audio_2x", NULL); | ||
800 | clks[audio_2x] = clk; | ||
801 | |||
802 | } | ||
803 | |||
804 | static const char *i2s1_parents[] = {"pll_a_out0", "audio_2x", "pll_p", | ||
805 | "clk_m"}; | ||
806 | static const char *i2s2_parents[] = {"pll_a_out0", "audio_2x", "pll_p", | ||
807 | "clk_m"}; | ||
808 | static const char *spdif_out_parents[] = {"pll_a_out0", "audio_2x", "pll_p", | ||
809 | "clk_m"}; | ||
810 | static const char *spdif_in_parents[] = {"pll_p", "pll_c", "pll_m"}; | ||
811 | static const char *pwm_parents[] = {"pll_p", "pll_c", "audio", "clk_m", | ||
812 | "clk_32k"}; | ||
813 | static const char *mux_pllpcm_clkm[] = {"pll_p", "pll_c", "pll_m", "clk_m"}; | ||
814 | static const char *mux_pllmcpa[] = {"pll_m", "pll_c", "pll_c", "pll_a"}; | ||
815 | static const char *mux_pllpdc_clkm[] = {"pll_p", "pll_d_out0", "pll_c", | ||
816 | "clk_m"}; | ||
817 | static const char *mux_pllmcp_clkm[] = {"pll_m", "pll_c", "pll_p", "clk_m"}; | ||
818 | |||
819 | static struct tegra_periph_init_data tegra_periph_clk_list[] = { | ||
820 | TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra20-i2s.0", i2s1_parents, CLK_SOURCE_I2S1, 11, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s1), | ||
821 | TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra20-i2s.1", i2s2_parents, CLK_SOURCE_I2S2, 18, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s2), | ||
822 | TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra20-spdif", spdif_out_parents, CLK_SOURCE_SPDIF_OUT, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_out), | ||
823 | TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra20-spdif", spdif_in_parents, CLK_SOURCE_SPDIF_IN, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_in), | ||
824 | TEGRA_INIT_DATA_MUX("sbc1", NULL, "spi_tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SBC1, 41, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc1), | ||
825 | TEGRA_INIT_DATA_MUX("sbc2", NULL, "spi_tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SBC2, 44, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc2), | ||
826 | TEGRA_INIT_DATA_MUX("sbc3", NULL, "spi_tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SBC3, 46, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc3), | ||
827 | TEGRA_INIT_DATA_MUX("sbc4", NULL, "spi_tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SBC4, 68, &periph_u_regs, TEGRA_PERIPH_ON_APB, sbc4), | ||
828 | TEGRA_INIT_DATA_MUX("spi", NULL, "spi", mux_pllpcm_clkm, CLK_SOURCE_SPI, 43, &periph_h_regs, TEGRA_PERIPH_ON_APB, spi), | ||
829 | TEGRA_INIT_DATA_MUX("xio", NULL, "xio", mux_pllpcm_clkm, CLK_SOURCE_XIO, 45, &periph_h_regs, 0, xio), | ||
830 | TEGRA_INIT_DATA_MUX("twc", NULL, "twc", mux_pllpcm_clkm, CLK_SOURCE_TWC, 16, &periph_l_regs, TEGRA_PERIPH_ON_APB, twc), | ||
831 | TEGRA_INIT_DATA_MUX("ide", NULL, "ide", mux_pllpcm_clkm, CLK_SOURCE_XIO, 25, &periph_l_regs, 0, ide), | ||
832 | TEGRA_INIT_DATA_MUX("ndflash", NULL, "tegra_nand", mux_pllpcm_clkm, CLK_SOURCE_NDFLASH, 13, &periph_l_regs, 0, ndflash), | ||
833 | TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllpcm_clkm, CLK_SOURCE_VFIR, 7, &periph_l_regs, TEGRA_PERIPH_ON_APB, vfir), | ||
834 | TEGRA_INIT_DATA_MUX("csite", NULL, "csite", mux_pllpcm_clkm, CLK_SOURCE_CSITE, 73, &periph_u_regs, 0, csite), | ||
835 | TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllpcm_clkm, CLK_SOURCE_LA, 76, &periph_u_regs, 0, la), | ||
836 | TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllpcm_clkm, CLK_SOURCE_OWR, 71, &periph_u_regs, TEGRA_PERIPH_ON_APB, owr), | ||
837 | TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllpcm_clkm, CLK_SOURCE_MIPI, 50, &periph_h_regs, TEGRA_PERIPH_ON_APB, mipi), | ||
838 | TEGRA_INIT_DATA_MUX("vde", NULL, "vde", mux_pllpcm_clkm, CLK_SOURCE_VDE, 61, &periph_h_regs, 0, vde), | ||
839 | TEGRA_INIT_DATA_MUX("vi", "vi", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI, 20, &periph_l_regs, 0, vi), | ||
840 | TEGRA_INIT_DATA_MUX("epp", NULL, "epp", mux_pllmcpa, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, epp), | ||
841 | TEGRA_INIT_DATA_MUX("mpe", NULL, "mpe", mux_pllmcpa, CLK_SOURCE_MPE, 60, &periph_h_regs, 0, mpe), | ||
842 | TEGRA_INIT_DATA_MUX("host1x", NULL, "host1x", mux_pllmcpa, CLK_SOURCE_HOST1X, 28, &periph_l_regs, 0, host1x), | ||
843 | TEGRA_INIT_DATA_MUX("3d", NULL, "3d", mux_pllmcpa, CLK_SOURCE_3D, 24, &periph_l_regs, TEGRA_PERIPH_MANUAL_RESET, gr3d), | ||
844 | TEGRA_INIT_DATA_MUX("2d", NULL, "2d", mux_pllmcpa, CLK_SOURCE_2D, 21, &periph_l_regs, 0, gr2d), | ||
845 | TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllpcm_clkm, CLK_SOURCE_NOR, 42, &periph_h_regs, 0, nor), | ||
846 | TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllpcm_clkm, CLK_SOURCE_SDMMC1, 14, &periph_l_regs, 0, sdmmc1), | ||
847 | TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllpcm_clkm, CLK_SOURCE_SDMMC2, 9, &periph_l_regs, 0, sdmmc2), | ||
848 | TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllpcm_clkm, CLK_SOURCE_SDMMC3, 69, &periph_u_regs, 0, sdmmc3), | ||
849 | TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllpcm_clkm, CLK_SOURCE_SDMMC4, 15, &periph_l_regs, 0, sdmmc4), | ||
850 | TEGRA_INIT_DATA_MUX("cve", NULL, "cve", mux_pllpdc_clkm, CLK_SOURCE_CVE, 49, &periph_h_regs, 0, cve), | ||
851 | TEGRA_INIT_DATA_MUX("tvo", NULL, "tvo", mux_pllpdc_clkm, CLK_SOURCE_TVO, 49, &periph_h_regs, 0, tvo), | ||
852 | TEGRA_INIT_DATA_MUX("tvdac", NULL, "tvdac", mux_pllpdc_clkm, CLK_SOURCE_TVDAC, 53, &periph_h_regs, 0, tvdac), | ||
853 | TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllmcpa, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor), | ||
854 | TEGRA_INIT_DATA_DIV16("i2c1", "div-clk", "tegra-i2c.0", mux_pllpcm_clkm, CLK_SOURCE_I2C1, 12, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2c1), | ||
855 | TEGRA_INIT_DATA_DIV16("i2c2", "div-clk", "tegra-i2c.1", mux_pllpcm_clkm, CLK_SOURCE_I2C2, 54, &periph_h_regs, TEGRA_PERIPH_ON_APB, i2c2), | ||
856 | TEGRA_INIT_DATA_DIV16("i2c3", "div-clk", "tegra-i2c.2", mux_pllpcm_clkm, CLK_SOURCE_I2C3, 67, &periph_u_regs, TEGRA_PERIPH_ON_APB, i2c3), | ||
857 | TEGRA_INIT_DATA_DIV16("dvc", "div-clk", "tegra-i2c.3", mux_pllpcm_clkm, CLK_SOURCE_DVC, 47, &periph_h_regs, TEGRA_PERIPH_ON_APB, dvc), | ||
858 | TEGRA_INIT_DATA_MUX("hdmi", NULL, "hdmi", mux_pllpdc_clkm, CLK_SOURCE_HDMI, 51, &periph_h_regs, 0, hdmi), | ||
859 | TEGRA_INIT_DATA("pwm", NULL, "tegra-pwm", pwm_parents, CLK_SOURCE_PWM, 28, 3, 0, 0, 8, 1, 0, &periph_l_regs, 17, periph_clk_enb_refcnt, TEGRA_PERIPH_ON_APB, pwm), | ||
860 | }; | ||
861 | |||
862 | static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = { | ||
863 | TEGRA_INIT_DATA_NODIV("uarta", NULL, "tegra_uart.0", mux_pllpcm_clkm, CLK_SOURCE_UARTA, 30, 2, 6, &periph_l_regs, TEGRA_PERIPH_ON_APB, uarta), | ||
864 | TEGRA_INIT_DATA_NODIV("uartb", NULL, "tegra_uart.1", mux_pllpcm_clkm, CLK_SOURCE_UARTB, 30, 2, 7, &periph_l_regs, TEGRA_PERIPH_ON_APB, uartb), | ||
865 | TEGRA_INIT_DATA_NODIV("uartc", NULL, "tegra_uart.2", mux_pllpcm_clkm, CLK_SOURCE_UARTC, 30, 2, 55, &periph_h_regs, TEGRA_PERIPH_ON_APB, uartc), | ||
866 | TEGRA_INIT_DATA_NODIV("uartd", NULL, "tegra_uart.3", mux_pllpcm_clkm, CLK_SOURCE_UARTD, 30, 2, 65, &periph_u_regs, TEGRA_PERIPH_ON_APB, uartd), | ||
867 | TEGRA_INIT_DATA_NODIV("uarte", NULL, "tegra_uart.4", mux_pllpcm_clkm, CLK_SOURCE_UARTE, 30, 2, 66, &periph_u_regs, TEGRA_PERIPH_ON_APB, uarte), | ||
868 | TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllpdc_clkm, CLK_SOURCE_DISP1, 30, 2, 27, &periph_l_regs, 0, disp1), | ||
869 | TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllpdc_clkm, CLK_SOURCE_DISP2, 30, 2, 26, &periph_l_regs, 0, disp2), | ||
870 | }; | ||
871 | |||
872 | static void __init tegra20_periph_clk_init(void) | ||
873 | { | ||
874 | struct tegra_periph_init_data *data; | ||
875 | struct clk *clk; | ||
876 | int i; | ||
877 | |||
878 | /* apbdma */ | ||
879 | clk = tegra_clk_register_periph_gate("apbdma", "pclk", 0, clk_base, | ||
880 | 0, 34, &periph_h_regs, | ||
881 | periph_clk_enb_refcnt); | ||
882 | clk_register_clkdev(clk, NULL, "tegra-apbdma"); | ||
883 | clks[apbdma] = clk; | ||
884 | |||
885 | /* rtc */ | ||
886 | clk = tegra_clk_register_periph_gate("rtc", "clk_32k", | ||
887 | TEGRA_PERIPH_NO_RESET, | ||
888 | clk_base, 0, 4, &periph_l_regs, | ||
889 | periph_clk_enb_refcnt); | ||
890 | clk_register_clkdev(clk, NULL, "rtc-tegra"); | ||
891 | clks[rtc] = clk; | ||
892 | |||
893 | /* timer */ | ||
894 | clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base, | ||
895 | 0, 5, &periph_l_regs, | ||
896 | periph_clk_enb_refcnt); | ||
897 | clk_register_clkdev(clk, NULL, "timer"); | ||
898 | clks[timer] = clk; | ||
899 | |||
900 | /* kbc */ | ||
901 | clk = tegra_clk_register_periph_gate("kbc", "clk_32k", | ||
902 | TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB, | ||
903 | clk_base, 0, 36, &periph_h_regs, | ||
904 | periph_clk_enb_refcnt); | ||
905 | clk_register_clkdev(clk, NULL, "tegra-kbc"); | ||
906 | clks[kbc] = clk; | ||
907 | |||
908 | /* csus */ | ||
909 | clk = tegra_clk_register_periph_gate("csus", "clk_m", | ||
910 | TEGRA_PERIPH_NO_RESET, | ||
911 | clk_base, 0, 92, &periph_u_regs, | ||
912 | periph_clk_enb_refcnt); | ||
913 | clk_register_clkdev(clk, "csus", "tengra_camera"); | ||
914 | clks[csus] = clk; | ||
915 | |||
916 | /* vcp */ | ||
917 | clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0, | ||
918 | clk_base, 0, 29, &periph_l_regs, | ||
919 | periph_clk_enb_refcnt); | ||
920 | clk_register_clkdev(clk, "vcp", "tegra-avp"); | ||
921 | clks[vcp] = clk; | ||
922 | |||
923 | /* bsea */ | ||
924 | clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0, | ||
925 | clk_base, 0, 62, &periph_h_regs, | ||
926 | periph_clk_enb_refcnt); | ||
927 | clk_register_clkdev(clk, "bsea", "tegra-avp"); | ||
928 | clks[bsea] = clk; | ||
929 | |||
930 | /* bsev */ | ||
931 | clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0, | ||
932 | clk_base, 0, 63, &periph_h_regs, | ||
933 | periph_clk_enb_refcnt); | ||
934 | clk_register_clkdev(clk, "bsev", "tegra-aes"); | ||
935 | clks[bsev] = clk; | ||
936 | |||
937 | /* emc */ | ||
938 | clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, | ||
939 | ARRAY_SIZE(mux_pllmcp_clkm), 0, | ||
940 | clk_base + CLK_SOURCE_EMC, | ||
941 | 30, 2, 0, NULL); | ||
942 | clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0, | ||
943 | 57, &periph_h_regs, periph_clk_enb_refcnt); | ||
944 | clk_register_clkdev(clk, "emc", NULL); | ||
945 | clks[emc] = clk; | ||
946 | |||
947 | /* usbd */ | ||
948 | clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base, 0, | ||
949 | 22, &periph_l_regs, periph_clk_enb_refcnt); | ||
950 | clk_register_clkdev(clk, NULL, "fsl-tegra-udc"); | ||
951 | clks[usbd] = clk; | ||
952 | |||
953 | /* usb2 */ | ||
954 | clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base, 0, | ||
955 | 58, &periph_h_regs, periph_clk_enb_refcnt); | ||
956 | clk_register_clkdev(clk, NULL, "tegra-ehci.1"); | ||
957 | clks[usb2] = clk; | ||
958 | |||
959 | /* usb3 */ | ||
960 | clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base, 0, | ||
961 | 59, &periph_h_regs, periph_clk_enb_refcnt); | ||
962 | clk_register_clkdev(clk, NULL, "tegra-ehci.2"); | ||
963 | clks[usb3] = clk; | ||
964 | |||
965 | /* dsi */ | ||
966 | clk = tegra_clk_register_periph_gate("dsi", "pll_d", 0, clk_base, 0, | ||
967 | 48, &periph_h_regs, periph_clk_enb_refcnt); | ||
968 | clk_register_clkdev(clk, NULL, "dsi"); | ||
969 | clks[dsi] = clk; | ||
970 | |||
971 | /* csi */ | ||
972 | clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base, | ||
973 | 0, 52, &periph_h_regs, | ||
974 | periph_clk_enb_refcnt); | ||
975 | clk_register_clkdev(clk, "csi", "tegra_camera"); | ||
976 | clks[csi] = clk; | ||
977 | |||
978 | /* isp */ | ||
979 | clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0, 23, | ||
980 | &periph_l_regs, periph_clk_enb_refcnt); | ||
981 | clk_register_clkdev(clk, "isp", "tegra_camera"); | ||
982 | clks[isp] = clk; | ||
983 | |||
984 | /* pex */ | ||
985 | clk = tegra_clk_register_periph_gate("pex", "clk_m", 0, clk_base, 0, 70, | ||
986 | &periph_u_regs, periph_clk_enb_refcnt); | ||
987 | clk_register_clkdev(clk, "pex", NULL); | ||
988 | clks[pex] = clk; | ||
989 | |||
990 | /* afi */ | ||
991 | clk = tegra_clk_register_periph_gate("afi", "clk_m", 0, clk_base, 0, 72, | ||
992 | &periph_u_regs, periph_clk_enb_refcnt); | ||
993 | clk_register_clkdev(clk, "afi", NULL); | ||
994 | clks[afi] = clk; | ||
995 | |||
996 | /* pcie_xclk */ | ||
997 | clk = tegra_clk_register_periph_gate("pcie_xclk", "clk_m", 0, clk_base, | ||
998 | 0, 74, &periph_u_regs, | ||
999 | periph_clk_enb_refcnt); | ||
1000 | clk_register_clkdev(clk, "pcie_xclk", NULL); | ||
1001 | clks[pcie_xclk] = clk; | ||
1002 | |||
1003 | /* cdev1 */ | ||
1004 | clk = clk_register_fixed_rate(NULL, "cdev1_fixed", NULL, CLK_IS_ROOT, | ||
1005 | 26000000); | ||
1006 | clk = tegra_clk_register_periph_gate("cdev1", "cdev1_fixed", 0, | ||
1007 | clk_base, 0, 94, &periph_u_regs, | ||
1008 | periph_clk_enb_refcnt); | ||
1009 | clk_register_clkdev(clk, "cdev1", NULL); | ||
1010 | clks[cdev1] = clk; | ||
1011 | |||
1012 | /* cdev2 */ | ||
1013 | clk = clk_register_fixed_rate(NULL, "cdev2_fixed", NULL, CLK_IS_ROOT, | ||
1014 | 26000000); | ||
1015 | clk = tegra_clk_register_periph_gate("cdev2", "cdev2_fixed", 0, | ||
1016 | clk_base, 0, 93, &periph_u_regs, | ||
1017 | periph_clk_enb_refcnt); | ||
1018 | clk_register_clkdev(clk, "cdev2", NULL); | ||
1019 | clks[cdev2] = clk; | ||
1020 | |||
1021 | for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { | ||
1022 | data = &tegra_periph_clk_list[i]; | ||
1023 | clk = tegra_clk_register_periph(data->name, data->parent_names, | ||
1024 | data->num_parents, &data->periph, | ||
1025 | clk_base, data->offset); | ||
1026 | clk_register_clkdev(clk, data->con_id, data->dev_id); | ||
1027 | clks[data->clk_id] = clk; | ||
1028 | } | ||
1029 | |||
1030 | for (i = 0; i < ARRAY_SIZE(tegra_periph_nodiv_clk_list); i++) { | ||
1031 | data = &tegra_periph_nodiv_clk_list[i]; | ||
1032 | clk = tegra_clk_register_periph_nodiv(data->name, | ||
1033 | data->parent_names, | ||
1034 | data->num_parents, &data->periph, | ||
1035 | clk_base, data->offset); | ||
1036 | clk_register_clkdev(clk, data->con_id, data->dev_id); | ||
1037 | clks[data->clk_id] = clk; | ||
1038 | } | ||
1039 | } | ||
1040 | |||
1041 | |||
1042 | static void __init tegra20_fixed_clk_init(void) | ||
1043 | { | ||
1044 | struct clk *clk; | ||
1045 | |||
1046 | /* clk_32k */ | ||
1047 | clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, CLK_IS_ROOT, | ||
1048 | 32768); | ||
1049 | clk_register_clkdev(clk, "clk_32k", NULL); | ||
1050 | clks[clk_32k] = clk; | ||
1051 | } | ||
1052 | |||
1053 | static void __init tegra20_pmc_clk_init(void) | ||
1054 | { | ||
1055 | struct clk *clk; | ||
1056 | |||
1057 | /* blink */ | ||
1058 | writel_relaxed(0, pmc_base + PMC_BLINK_TIMER); | ||
1059 | clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0, | ||
1060 | pmc_base + PMC_DPD_PADS_ORIDE, | ||
1061 | PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL); | ||
1062 | clk = clk_register_gate(NULL, "blink", "blink_override", 0, | ||
1063 | pmc_base + PMC_CTRL, | ||
1064 | PMC_CTRL_BLINK_ENB, 0, NULL); | ||
1065 | clk_register_clkdev(clk, "blink", NULL); | ||
1066 | clks[blink] = clk; | ||
1067 | } | ||
1068 | |||
1069 | static void __init tegra20_osc_clk_init(void) | ||
1070 | { | ||
1071 | struct clk *clk; | ||
1072 | unsigned long input_freq; | ||
1073 | unsigned int pll_ref_div; | ||
1074 | |||
1075 | input_freq = tegra20_clk_measure_input_freq(); | ||
1076 | |||
1077 | /* clk_m */ | ||
1078 | clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT | | ||
1079 | CLK_IGNORE_UNUSED, input_freq); | ||
1080 | clk_register_clkdev(clk, "clk_m", NULL); | ||
1081 | clks[clk_m] = clk; | ||
1082 | |||
1083 | /* pll_ref */ | ||
1084 | pll_ref_div = tegra20_get_pll_ref_div(); | ||
1085 | clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m", | ||
1086 | CLK_SET_RATE_PARENT, 1, pll_ref_div); | ||
1087 | clk_register_clkdev(clk, "pll_ref", NULL); | ||
1088 | clks[pll_ref] = clk; | ||
1089 | } | ||
1090 | |||
1091 | /* Tegra20 CPU clock and reset control functions */ | ||
1092 | static void tegra20_wait_cpu_in_reset(u32 cpu) | ||
1093 | { | ||
1094 | unsigned int reg; | ||
1095 | |||
1096 | do { | ||
1097 | reg = readl(clk_base + | ||
1098 | TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET); | ||
1099 | cpu_relax(); | ||
1100 | } while (!(reg & (1 << cpu))); /* check CPU been reset or not */ | ||
1101 | |||
1102 | return; | ||
1103 | } | ||
1104 | |||
1105 | static void tegra20_put_cpu_in_reset(u32 cpu) | ||
1106 | { | ||
1107 | writel(CPU_RESET(cpu), | ||
1108 | clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET); | ||
1109 | dmb(); | ||
1110 | } | ||
1111 | |||
1112 | static void tegra20_cpu_out_of_reset(u32 cpu) | ||
1113 | { | ||
1114 | writel(CPU_RESET(cpu), | ||
1115 | clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR); | ||
1116 | wmb(); | ||
1117 | } | ||
1118 | |||
1119 | static void tegra20_enable_cpu_clock(u32 cpu) | ||
1120 | { | ||
1121 | unsigned int reg; | ||
1122 | |||
1123 | reg = readl(clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); | ||
1124 | writel(reg & ~CPU_CLOCK(cpu), | ||
1125 | clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); | ||
1126 | barrier(); | ||
1127 | reg = readl(clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); | ||
1128 | } | ||
1129 | |||
1130 | static void tegra20_disable_cpu_clock(u32 cpu) | ||
1131 | { | ||
1132 | unsigned int reg; | ||
1133 | |||
1134 | reg = readl(clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); | ||
1135 | writel(reg | CPU_CLOCK(cpu), | ||
1136 | clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); | ||
1137 | } | ||
1138 | |||
1139 | static struct tegra_cpu_car_ops tegra20_cpu_car_ops = { | ||
1140 | .wait_for_reset = tegra20_wait_cpu_in_reset, | ||
1141 | .put_in_reset = tegra20_put_cpu_in_reset, | ||
1142 | .out_of_reset = tegra20_cpu_out_of_reset, | ||
1143 | .enable_clock = tegra20_enable_cpu_clock, | ||
1144 | .disable_clock = tegra20_disable_cpu_clock, | ||
1145 | }; | ||
1146 | |||
1147 | static __initdata struct tegra_clk_init_table init_table[] = { | ||
1148 | {pll_p, clk_max, 216000000, 1}, | ||
1149 | {pll_p_out1, clk_max, 28800000, 1}, | ||
1150 | {pll_p_out2, clk_max, 48000000, 1}, | ||
1151 | {pll_p_out3, clk_max, 72000000, 1}, | ||
1152 | {pll_p_out4, clk_max, 24000000, 1}, | ||
1153 | {pll_c, clk_max, 600000000, 1}, | ||
1154 | {pll_c_out1, clk_max, 120000000, 1}, | ||
1155 | {sclk, pll_c_out1, 0, 1}, | ||
1156 | {hclk, clk_max, 0, 1}, | ||
1157 | {pclk, clk_max, 60000000, 1}, | ||
1158 | {csite, clk_max, 0, 1}, | ||
1159 | {emc, clk_max, 0, 1}, | ||
1160 | {cclk, clk_max, 0, 1}, | ||
1161 | {uarta, pll_p, 0, 1}, | ||
1162 | {uartd, pll_p, 0, 1}, | ||
1163 | {usbd, clk_max, 12000000, 0}, | ||
1164 | {usb2, clk_max, 12000000, 0}, | ||
1165 | {usb3, clk_max, 12000000, 0}, | ||
1166 | {pll_a, clk_max, 56448000, 1}, | ||
1167 | {pll_a_out0, clk_max, 11289600, 1}, | ||
1168 | {cdev1, clk_max, 0, 1}, | ||
1169 | {blink, clk_max, 32768, 1}, | ||
1170 | {i2s1, pll_a_out0, 11289600, 0}, | ||
1171 | {i2s2, pll_a_out0, 11289600, 0}, | ||
1172 | {sdmmc1, pll_p, 48000000, 0}, | ||
1173 | {sdmmc3, pll_p, 48000000, 0}, | ||
1174 | {sdmmc4, pll_p, 48000000, 0}, | ||
1175 | {spi, pll_p, 20000000, 0}, | ||
1176 | {sbc1, pll_p, 100000000, 0}, | ||
1177 | {sbc2, pll_p, 100000000, 0}, | ||
1178 | {sbc3, pll_p, 100000000, 0}, | ||
1179 | {sbc4, pll_p, 100000000, 0}, | ||
1180 | {host1x, pll_c, 150000000, 0}, | ||
1181 | {disp1, pll_p, 600000000, 0}, | ||
1182 | {disp2, pll_p, 600000000, 0}, | ||
1183 | {clk_max, clk_max, 0, 0}, /* This MUST be the last entry */ | ||
1184 | }; | ||
1185 | |||
1186 | /* | ||
1187 | * Some clocks may be used by different drivers depending on the board | ||
1188 | * configuration. List those here to register them twice in the clock lookup | ||
1189 | * table under two names. | ||
1190 | */ | ||
1191 | static struct tegra_clk_duplicate tegra_clk_duplicates[] = { | ||
1192 | TEGRA_CLK_DUPLICATE(uarta, "serial8250.0", NULL), | ||
1193 | TEGRA_CLK_DUPLICATE(uartb, "serial8250.1", NULL), | ||
1194 | TEGRA_CLK_DUPLICATE(uartc, "serial8250.2", NULL), | ||
1195 | TEGRA_CLK_DUPLICATE(uartd, "serial8250.3", NULL), | ||
1196 | TEGRA_CLK_DUPLICATE(uarte, "serial8250.4", NULL), | ||
1197 | TEGRA_CLK_DUPLICATE(usbd, "utmip-pad", NULL), | ||
1198 | TEGRA_CLK_DUPLICATE(usbd, "tegra-ehci.0", NULL), | ||
1199 | TEGRA_CLK_DUPLICATE(usbd, "tegra-otg", NULL), | ||
1200 | TEGRA_CLK_DUPLICATE(pll_p, "tegradc.0", "parent"), | ||
1201 | TEGRA_CLK_DUPLICATE(pll_p, "tegradc.1", "parent"), | ||
1202 | TEGRA_CLK_DUPLICATE(pll_d_out0, "hdmi", "parent"), | ||
1203 | TEGRA_CLK_DUPLICATE(gr2d, "tegra_grhost", "gr2d"), | ||
1204 | TEGRA_CLK_DUPLICATE(gr3d, "tegra_grhost", "gr3d"), | ||
1205 | TEGRA_CLK_DUPLICATE(epp, "tegra_grhost", "epp"), | ||
1206 | TEGRA_CLK_DUPLICATE(mpe, "tegra_grhost", "mpe"), | ||
1207 | TEGRA_CLK_DUPLICATE(vde, "tegra-aes", "vde"), | ||
1208 | TEGRA_CLK_DUPLICATE(cclk, NULL, "cpu"), | ||
1209 | TEGRA_CLK_DUPLICATE(twd, "smp_twd", NULL), | ||
1210 | TEGRA_CLK_DUPLICATE(pll_p_out3, "tegra-i2c.0", "fast-clk"), | ||
1211 | TEGRA_CLK_DUPLICATE(pll_p_out3, "tegra-i2c.1", "fast-clk"), | ||
1212 | TEGRA_CLK_DUPLICATE(pll_p_out3, "tegra-i2c.2", "fast-clk"), | ||
1213 | TEGRA_CLK_DUPLICATE(pll_p_out3, "tegra-i2c.3", "fast-clk"), | ||
1214 | TEGRA_CLK_DUPLICATE(clk_max, NULL, NULL), /* Must be the last entry */ | ||
1215 | }; | ||
1216 | |||
1217 | static const struct of_device_id pmc_match[] __initconst = { | ||
1218 | { .compatible = "nvidia,tegra20-pmc" }, | ||
1219 | {}, | ||
1220 | }; | ||
1221 | |||
1222 | void __init tegra20_clock_init(struct device_node *np) | ||
1223 | { | ||
1224 | int i; | ||
1225 | struct device_node *node; | ||
1226 | |||
1227 | clk_base = of_iomap(np, 0); | ||
1228 | if (!clk_base) { | ||
1229 | pr_err("Can't map CAR registers\n"); | ||
1230 | BUG(); | ||
1231 | } | ||
1232 | |||
1233 | node = of_find_matching_node(NULL, pmc_match); | ||
1234 | if (!node) { | ||
1235 | pr_err("Failed to find pmc node\n"); | ||
1236 | BUG(); | ||
1237 | } | ||
1238 | |||
1239 | pmc_base = of_iomap(node, 0); | ||
1240 | if (!pmc_base) { | ||
1241 | pr_err("Can't map pmc registers\n"); | ||
1242 | BUG(); | ||
1243 | } | ||
1244 | |||
1245 | tegra20_osc_clk_init(); | ||
1246 | tegra20_pmc_clk_init(); | ||
1247 | tegra20_fixed_clk_init(); | ||
1248 | tegra20_pll_init(); | ||
1249 | tegra20_super_clk_init(); | ||
1250 | tegra20_periph_clk_init(); | ||
1251 | tegra20_audio_clk_init(); | ||
1252 | |||
1253 | |||
1254 | for (i = 0; i < ARRAY_SIZE(clks); i++) { | ||
1255 | if (IS_ERR(clks[i])) { | ||
1256 | pr_err("Tegra20 clk %d: register failed with %ld\n", | ||
1257 | i, PTR_ERR(clks[i])); | ||
1258 | BUG(); | ||
1259 | } | ||
1260 | if (!clks[i]) | ||
1261 | clks[i] = ERR_PTR(-EINVAL); | ||
1262 | } | ||
1263 | |||
1264 | tegra_init_dup_clks(tegra_clk_duplicates, clks, clk_max); | ||
1265 | |||
1266 | clk_data.clks = clks; | ||
1267 | clk_data.clk_num = ARRAY_SIZE(clks); | ||
1268 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | ||
1269 | |||
1270 | tegra_init_from_table(init_table, clks, clk_max); | ||
1271 | |||
1272 | tegra_cpu_car_ops = &tegra20_cpu_car_ops; | ||
1273 | } | ||
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 5fcfa51d6b17..82835f24533c 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h | |||
@@ -487,4 +487,10 @@ void tegra_init_from_table(struct tegra_clk_init_table *tbl, | |||
487 | void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, | 487 | void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, |
488 | struct clk *clks[], int clk_max); | 488 | struct clk *clks[], int clk_max); |
489 | 489 | ||
490 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC | ||
491 | void tegra20_clock_init(struct device_node *np); | ||
492 | #else | ||
493 | static inline void tegra20_clock_init(struct device_node *np) {} | ||
494 | #endif /* CONFIG_ARCH_TEGRA_2x_SOC */ | ||
495 | |||
490 | #endif /* TEGRA_CLK_H */ | 496 | #endif /* TEGRA_CLK_H */ |