blob: f1dcba7d9178a285ea3fc8bc1e8b5443e2de70ba [file] [log] [blame]
Deepa Dinamani7dc3d4b2013-02-08 16:40:38 -08001/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <err.h>
30#include <assert.h>
31#include <debug.h>
32#include <reg.h>
33#include <platform/timer.h>
34#include <platform/iomap.h>
35#include <mmc.h>
36#include <clock.h>
37#include <platform/clock.h>
38
39void hsusb_clock_init(void)
40{
Deepa Dinamanie1666ac2013-03-20 16:19:38 -070041 int ret;
42 struct clk *iclk, *cclk;
43
44 ret = clk_get_set_enable("usb_iface_clk", 0, 1);
45 if(ret)
46 {
47 dprintf(CRITICAL, "failed to set usb_iface_clk ret = %d\n", ret);
48 ASSERT(0);
49 }
50
51 ret = clk_get_set_enable("usb_core_clk", 75000000, 1);
52 if(ret)
53 {
54 dprintf(CRITICAL, "failed to set usb_core_clk ret = %d\n", ret);
55 ASSERT(0);
56 }
57
58 /* Wait for the clocks to be stable since we are disabling soon after. */
59 mdelay(1);
60
61 iclk = clk_get("usb_iface_clk");
62 cclk = clk_get("usb_core_clk");
63
64 clk_disable(iclk);
65 clk_disable(cclk);
66
67 /* Wait for the clock disable to complete. */
68 mdelay(1);
69
70 /* Start the block reset for usb */
71 writel(1, USB_HS_BCR);
72
73 /* Wait for reset to complete. */
74 mdelay(1);
75
76 /* Take usb block out of reset */
77 writel(0, USB_HS_BCR);
78
79 /* Wait for the block to be brought out of reset. */
80 mdelay(1);
81
82 ret = clk_enable(iclk);
83
84 if(ret)
85 {
86 dprintf(CRITICAL, "failed to set usb_iface_clk after async ret = %d\n", ret);
87 ASSERT(0);
88 }
89
90 ret = clk_enable(cclk);
91
92 if(ret)
93 {
94 dprintf(CRITICAL, "failed to set usb_iface_clk after async ret = %d\n", ret);
95 ASSERT(0);
96 }
97
Deepa Dinamani7dc3d4b2013-02-08 16:40:38 -080098}
99
100void clock_init_mmc(uint32_t interface)
101{
Deepa Dinamanie1666ac2013-03-20 16:19:38 -0700102 char clk_name[64];
103 int ret;
104
105 snprintf(clk_name, 64, "sdc%u_iface_clk", interface);
106
107 /* enable interface clock */
108 ret = clk_get_set_enable(clk_name, 0, 1);
109 if(ret)
110 {
111 dprintf(CRITICAL, "failed to set sdc1_iface_clk ret = %d\n", ret);
112 ASSERT(0);
113 }
Deepa Dinamani7dc3d4b2013-02-08 16:40:38 -0800114}
115
116/* Configure MMC clock */
117void clock_config_mmc(uint32_t interface, uint32_t freq)
118{
Deepa Dinamanie1666ac2013-03-20 16:19:38 -0700119 int ret;
120 char clk_name[64];
Deepa Dinamani7dc3d4b2013-02-08 16:40:38 -0800121
Deepa Dinamanie1666ac2013-03-20 16:19:38 -0700122 snprintf(clk_name, 64, "sdc%u_core_clk", interface);
Deepa Dinamani7dc3d4b2013-02-08 16:40:38 -0800123
Deepa Dinamanie1666ac2013-03-20 16:19:38 -0700124 /* Disalbe MCI_CLK before changing the sdcc clock */
125 mmc_boot_mci_clk_disable();
Deepa Dinamani7dc3d4b2013-02-08 16:40:38 -0800126
Deepa Dinamanie1666ac2013-03-20 16:19:38 -0700127 if(freq == MMC_CLK_400KHZ)
128 {
129 ret = clk_get_set_enable(clk_name, 400000, 1);
130 }
131 else if(freq == MMC_CLK_50MHZ)
132 {
133 ret = clk_get_set_enable(clk_name, 50000000, 1);
134 }
135 else
136 {
137 dprintf(CRITICAL, "sdc frequency (%d) is not supported\n", freq);
138 ASSERT(0);
139 }
140
141 if(ret)
142 {
143 dprintf(CRITICAL, "failed to set sdc1_core_clk ret = %d\n", ret);
144 ASSERT(0);
145 }
146
147 /* Enable MCI CLK */
148 mmc_boot_mci_clk_enable();
Deepa Dinamani7dc3d4b2013-02-08 16:40:38 -0800149}
150
151/* Configure UART clock based on the UART block id*/
152void clock_config_uart_dm(uint8_t id)
153{
Deepa Dinamanie1666ac2013-03-20 16:19:38 -0700154 int ret;
155
156 ret = clk_get_set_enable("uart2_iface_clk", 0, 1);
157 if(ret)
158 {
159 dprintf(CRITICAL, "failed to set uart2_iface_clk ret = %d\n", ret);
160 ASSERT(0);
161 }
162
163 ret = clk_get_set_enable("uart2_core_clk", 7372800, 1);
164 if(ret)
165 {
166 dprintf(CRITICAL, "failed to set uart2_core_clk ret = %d\n", ret);
167 ASSERT(0);
168 }
169}
170
171void clock_config_ce(uint8_t instance)
172{
Deepa Dinamani7dc3d4b2013-02-08 16:40:38 -0800173}
174
Terence Hampson711a9c22013-06-18 14:35:43 -0400175/* Configure MDP clock */
176void mdp_clock_enable(void)
177{
178 int ret;
179
180 ret = clk_get_set_enable("axi_clk_src", 100000000, 1);
181 if(ret)
182 {
183 dprintf(CRITICAL, "failed to set axi_clk_src ret = %d\n", ret);
184 ASSERT(0);
185 }
186
187 ret = clk_get_set_enable("mmss_mmssnoc_axi_clk", 0, 1);
188 if(ret)
189 {
190 dprintf(CRITICAL, "failed to set mmss_mmssnoc_axi_clk ret = %d\n", ret);
191 ASSERT(0);
192 }
193
194 ret = clk_get_set_enable("mmss_s0_axi_clk", 0, 1);
195 if(ret)
196 {
197 dprintf(CRITICAL, "failed to set mmss_s0_axi_clk ret = %d\n", ret);
198 ASSERT(0);
199 }
200
201 ret = clk_get_set_enable("mdp_ahb_clk", 0, 1);
202 if(ret)
203 {
204 dprintf(CRITICAL, "failed to set mdp_ahb_clk ret = %d\n", ret);
205 ASSERT(0);
206 }
207
208 ret = clk_get_set_enable("mdp_axi_clk" , 0, 1);
209 if(ret)
210 {
211 dprintf(CRITICAL, "failed to set mdp_axi_clk ret = %d\n", ret);
212 ASSERT(0);
213 }
214
215 ret = clk_get_set_enable("mdp_vsync_clk" , 0, 1);
216 if(ret)
217 {
218 dprintf(CRITICAL, "failed to set mdp_vsync_clk ret = %d\n", ret);
219 ASSERT(0);
220 }
221}
222
223void mdp_clock_disable(void)
224{
225 clk_disable(clk_get("mdp_vsync_clk"));
226 clk_disable(clk_get("mdp_axi_clk"));
227 clk_disable(clk_get("mdp_ahb_clk"));
228 clk_disable(clk_get("mmss_s0_axi_clk"));
229 clk_disable(clk_get("mmss_mmssnoc_axi_clk"));
230}
231
232int dsi_vco_set_rate(uint32_t rate)
233{
234 uint32_t temp, val;
235 unsigned long fb_divider;
236
237 temp = rate / 10;
238 val = VCO_PARENT_RATE / 10;
239 fb_divider = (temp * VCO_PREF_DIV_RATIO) / val;
240 fb_divider = fb_divider / 2 - 1;
241
242 temp = readl(DSIPHY_PLL_CTRL(1));
243 val = (temp & 0xFFFFFF00) | (fb_divider & 0xFF);
244 writel(val, DSIPHY_PLL_CTRL(1));
245
246 temp = readl(DSIPHY_PLL_CTRL(2));
247 val = (temp & 0xFFFFFFF8) | ((fb_divider >> 8) & 0x07);
248 writel(val, DSIPHY_PLL_CTRL(2));
249
250 temp = readl(DSIPHY_PLL_CTRL(3));
251 val = (temp & 0xFFFFFFC0) | (VCO_PREF_DIV_RATIO - 1);
252 writel(val, DSIPHY_PLL_CTRL(3));
253 return 0;
254}
255
256uint32_t dsi_vco_round_rate(uint32_t rate)
257{
258 uint32_t vco_rate = rate;
259
260 if (rate < VCO_MIN_RATE)
261 vco_rate = VCO_MIN_RATE;
262 else if (rate > VCO_MAX_RATE)
263 vco_rate = VCO_MAX_RATE;
264
265 return vco_rate;
266}
267
268int dsi_byte_clk_set(uint32_t *vcoclk_rate, uint32_t rate)
269{
270 int div, ret;
271 uint32_t vco_rate, bitclk_rate;
272 uint32_t temp, val;
273
274 bitclk_rate = 8 * rate;
275
276 for (div = 1; div < VCO_MAX_DIVIDER; div++)
277 {
278 vco_rate = dsi_vco_round_rate(bitclk_rate * div);
279
280 if (vco_rate == bitclk_rate * div)
281 break;
282
283 if (vco_rate < bitclk_rate * div)
284 return -1;
285 }
286
287 if (vco_rate != bitclk_rate * div)
288 return -1;
289
290 ret = dsi_vco_set_rate(vco_rate);
291 if (ret)
292 {
293 dprintf(CRITICAL, "fail to set vco rate, ret = %d\n", ret);
294 return ret;
295 }
296 *vcoclk_rate = vco_rate;
297
298 /* set the bit clk divider */
299 temp = readl(DSIPHY_PLL_CTRL(8));
300 val = (temp & 0xFFFFFFF0) | (div - 1);
301 writel(val, DSIPHY_PLL_CTRL(8));
302
303 /* set the byte clk divider */
304 temp = readl(DSIPHY_PLL_CTRL(9));
305 val = (temp & 0xFFFFFF00) | (vco_rate / rate - 1);
306 writel(val, DSIPHY_PLL_CTRL(9));
307
308 return 0;
309}
310
311int dsi_dsi_clk_set(uint32_t vco_rate, uint32_t rate)
312{
313 uint32_t temp, val;
314
315 if (vco_rate % rate != 0)
316 {
317 dprintf(CRITICAL, "dsiclk_set_rate invalid rate\n");
318 return -1;
319 }
320
321 temp = readl(DSIPHY_PLL_CTRL(10));
322 val = (temp & 0xFFFFFF00) | (vco_rate / rate - 1);
323 writel(val, DSIPHY_PLL_CTRL(10));
324
325 return 0;
326}
327
328void dsi_setup_dividers(uint32_t val, uint32_t cfg_rcgr,
329 uint32_t cmd_rcgr)
330{
331 uint32_t i = 0;
332 uint32_t term_cnt = 5000;
333 int32_t reg;
334
335 writel(val, cfg_rcgr);
336 writel(0x1, cmd_rcgr);
337 reg = readl(cmd_rcgr);
338 while (reg & 0x1)
339 {
340 i++;
341 if (i > term_cnt)
342 {
343 dprintf(CRITICAL, "some dsi clock not enabled"
344 "exceeded polling TIMEOUT!\n");
345 break;
346 }
347 udelay(1);
348 reg = readl(cmd_rcgr);
349 }
350}
351
352void vco_enable(int enable)
353{
354 if (enable)
355 {
356 writel(0x1, DSIPHY_PLL_CTRL(0));
357 while (!(readl(DSIPHY_PLL_READY) & 0x01))
358 udelay(1);
359 } else {
360 writel(0x0, DSIPHY_PLL_CTRL(0));
361 }
362}
363
364void dsi_clock_enable(uint32_t dsiclk_rate, uint32_t byteclk_rate)
365{
366 uint32_t vcoclk_rate;
367 int ret;
368
369 ret = clk_get_set_enable("dsi_ahb_clk", 0, 1);
370 if(ret)
371 {
372 dprintf(CRITICAL, "failed to set dsi_ahb_clk ret = %d\n", ret);
373 ASSERT(0);
374 }
375
376 ret = dsi_byte_clk_set(&vcoclk_rate, byteclk_rate);
377 if(ret)
378 {
379 dprintf(CRITICAL, "failed to set byteclk ret = %d\n", ret);
380 ASSERT(0);
381 }
382
383 ret = dsi_dsi_clk_set(vcoclk_rate, dsiclk_rate);
384 if(ret)
385 {
386 dprintf(CRITICAL, "failed to set dsiclk ret = %d\n", ret);
387 ASSERT(0);
388 }
389
390 vco_enable(1);
391
392 dsi_setup_dividers(0x105, DSI_PCLK_CFG_RCGR, DSI_PCLK_CMD_RCGR);
393 dsi_setup_dividers(0x101, DSI_BYTE_CFG_RCGR, DSI_BYTE_CMD_RCGR);
394 dsi_setup_dividers(0x101, DSI_CFG_RCGR, DSI_CMD_RCGR);
395
396 ret = clk_get_set_enable("dsi_clk", 0, 1);
397 if(ret)
398 {
399 dprintf(CRITICAL, "failed to set dsi_clk ret = %d\n", ret);
400 ASSERT(0);
401 }
402
403 ret = clk_get_set_enable("dsi_byte_clk", 0, 1);
404 if(ret)
405 {
406 dprintf(CRITICAL, "failed to set dsi_byte_clk ret = %d\n", ret);
407 ASSERT(0);
408 }
409
410 ret = clk_get_set_enable("dsi_esc_clk", 0, 1);
411 if(ret)
412 {
413 dprintf(CRITICAL, "failed to set dsi_esc_clk ret = %d\n", ret);
414 ASSERT(0);
415 }
416
417 ret = clk_get_set_enable("dsi_pclk_clk", 0, 1);
418 if(ret)
419 {
420 dprintf(CRITICAL, "failed to set dsi_pclk_clk ret = %d\n", ret);
421 ASSERT(0);
422 }
423
424 ret = clk_get_set_enable("mdp_lcdc_clk" , 0, 1);
425 if(ret)
426 {
427 dprintf(CRITICAL, "failed to set mdp_lcdc_clk ret = %d\n", ret);
428 ASSERT(0);
429 }
430
431 ret = clk_get_set_enable("mdp_dsi_clk" , 0, 1);
432 if(ret)
433 {
434 dprintf(CRITICAL, "failed to set mdp_dsi_clk ret = %d\n", ret);
435 ASSERT(0);
436 }
437}
438
439void dsi_clock_disable(void)
440{
441 clk_disable(clk_get("mdp_dsi_clk"));
442 clk_disable(clk_get("mdp_lcdc_clk"));
443 clk_disable(clk_get("dsi_pclk_clk"));
444 clk_disable(clk_get("dsi_esc_clk"));
445 clk_disable(clk_get("dsi_byte_clk"));
446 clk_disable(clk_get("dsi_clk"));
447 vco_enable(0);
448 clk_disable(clk_get("dsi_ahb_clk"));
449}