blob: ecb485420aca2091d29b6f80de500a57059d1767 [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 if(freq == MMC_CLK_400KHZ)
125 {
126 ret = clk_get_set_enable(clk_name, 400000, 1);
127 }
128 else if(freq == MMC_CLK_50MHZ)
129 {
130 ret = clk_get_set_enable(clk_name, 50000000, 1);
131 }
Channagoud Kadabi83208002013-05-09 15:50:45 -0700132 else if(freq == MMC_CLK_200MHZ)
133 {
134 ret = clk_get_set_enable(clk_name, 200000000, 1);
135 }
Deepa Dinamanie1666ac2013-03-20 16:19:38 -0700136 else
137 {
138 dprintf(CRITICAL, "sdc frequency (%d) is not supported\n", freq);
139 ASSERT(0);
140 }
141
142 if(ret)
143 {
144 dprintf(CRITICAL, "failed to set sdc1_core_clk ret = %d\n", ret);
145 ASSERT(0);
146 }
Deepa Dinamani7dc3d4b2013-02-08 16:40:38 -0800147}
148
149/* Configure UART clock based on the UART block id*/
150void clock_config_uart_dm(uint8_t id)
151{
Deepa Dinamanie1666ac2013-03-20 16:19:38 -0700152 int ret;
153
154 ret = clk_get_set_enable("uart2_iface_clk", 0, 1);
155 if(ret)
156 {
157 dprintf(CRITICAL, "failed to set uart2_iface_clk ret = %d\n", ret);
158 ASSERT(0);
159 }
160
161 ret = clk_get_set_enable("uart2_core_clk", 7372800, 1);
162 if(ret)
163 {
164 dprintf(CRITICAL, "failed to set uart2_core_clk ret = %d\n", ret);
165 ASSERT(0);
166 }
167}
168
Terence Hampson711a9c22013-06-18 14:35:43 -0400169/* Configure MDP clock */
170void mdp_clock_enable(void)
171{
172 int ret;
173
Terence Hampsonfc832c12013-08-21 16:21:39 -0400174 ret = clk_get_set_enable("axi_clk_src", 200000000, 1);
Terence Hampson711a9c22013-06-18 14:35:43 -0400175 if(ret)
176 {
177 dprintf(CRITICAL, "failed to set axi_clk_src ret = %d\n", ret);
178 ASSERT(0);
179 }
180
181 ret = clk_get_set_enable("mmss_mmssnoc_axi_clk", 0, 1);
182 if(ret)
183 {
184 dprintf(CRITICAL, "failed to set mmss_mmssnoc_axi_clk ret = %d\n", ret);
185 ASSERT(0);
186 }
187
188 ret = clk_get_set_enable("mmss_s0_axi_clk", 0, 1);
189 if(ret)
190 {
191 dprintf(CRITICAL, "failed to set mmss_s0_axi_clk ret = %d\n", ret);
192 ASSERT(0);
193 }
194
195 ret = clk_get_set_enable("mdp_ahb_clk", 0, 1);
196 if(ret)
197 {
198 dprintf(CRITICAL, "failed to set mdp_ahb_clk ret = %d\n", ret);
199 ASSERT(0);
200 }
201
202 ret = clk_get_set_enable("mdp_axi_clk" , 0, 1);
203 if(ret)
204 {
205 dprintf(CRITICAL, "failed to set mdp_axi_clk ret = %d\n", ret);
206 ASSERT(0);
207 }
208
209 ret = clk_get_set_enable("mdp_vsync_clk" , 0, 1);
210 if(ret)
211 {
212 dprintf(CRITICAL, "failed to set mdp_vsync_clk ret = %d\n", ret);
213 ASSERT(0);
214 }
215}
216
217void mdp_clock_disable(void)
218{
219 clk_disable(clk_get("mdp_vsync_clk"));
220 clk_disable(clk_get("mdp_axi_clk"));
221 clk_disable(clk_get("mdp_ahb_clk"));
222 clk_disable(clk_get("mmss_s0_axi_clk"));
223 clk_disable(clk_get("mmss_mmssnoc_axi_clk"));
224}
225
226int dsi_vco_set_rate(uint32_t rate)
227{
228 uint32_t temp, val;
229 unsigned long fb_divider;
230
231 temp = rate / 10;
232 val = VCO_PARENT_RATE / 10;
233 fb_divider = (temp * VCO_PREF_DIV_RATIO) / val;
234 fb_divider = fb_divider / 2 - 1;
235
236 temp = readl(DSIPHY_PLL_CTRL(1));
237 val = (temp & 0xFFFFFF00) | (fb_divider & 0xFF);
238 writel(val, DSIPHY_PLL_CTRL(1));
239
240 temp = readl(DSIPHY_PLL_CTRL(2));
241 val = (temp & 0xFFFFFFF8) | ((fb_divider >> 8) & 0x07);
242 writel(val, DSIPHY_PLL_CTRL(2));
243
244 temp = readl(DSIPHY_PLL_CTRL(3));
245 val = (temp & 0xFFFFFFC0) | (VCO_PREF_DIV_RATIO - 1);
246 writel(val, DSIPHY_PLL_CTRL(3));
247 return 0;
248}
249
250uint32_t dsi_vco_round_rate(uint32_t rate)
251{
252 uint32_t vco_rate = rate;
253
254 if (rate < VCO_MIN_RATE)
255 vco_rate = VCO_MIN_RATE;
256 else if (rate > VCO_MAX_RATE)
257 vco_rate = VCO_MAX_RATE;
258
259 return vco_rate;
260}
261
262int dsi_byte_clk_set(uint32_t *vcoclk_rate, uint32_t rate)
263{
264 int div, ret;
265 uint32_t vco_rate, bitclk_rate;
266 uint32_t temp, val;
267
268 bitclk_rate = 8 * rate;
269
270 for (div = 1; div < VCO_MAX_DIVIDER; div++)
271 {
272 vco_rate = dsi_vco_round_rate(bitclk_rate * div);
273
274 if (vco_rate == bitclk_rate * div)
275 break;
276
277 if (vco_rate < bitclk_rate * div)
278 return -1;
279 }
280
281 if (vco_rate != bitclk_rate * div)
282 return -1;
283
284 ret = dsi_vco_set_rate(vco_rate);
285 if (ret)
286 {
287 dprintf(CRITICAL, "fail to set vco rate, ret = %d\n", ret);
288 return ret;
289 }
290 *vcoclk_rate = vco_rate;
291
292 /* set the bit clk divider */
293 temp = readl(DSIPHY_PLL_CTRL(8));
294 val = (temp & 0xFFFFFFF0) | (div - 1);
295 writel(val, DSIPHY_PLL_CTRL(8));
296
297 /* set the byte clk divider */
298 temp = readl(DSIPHY_PLL_CTRL(9));
299 val = (temp & 0xFFFFFF00) | (vco_rate / rate - 1);
300 writel(val, DSIPHY_PLL_CTRL(9));
301
302 return 0;
303}
304
305int dsi_dsi_clk_set(uint32_t vco_rate, uint32_t rate)
306{
307 uint32_t temp, val;
308
309 if (vco_rate % rate != 0)
310 {
311 dprintf(CRITICAL, "dsiclk_set_rate invalid rate\n");
312 return -1;
313 }
314
315 temp = readl(DSIPHY_PLL_CTRL(10));
316 val = (temp & 0xFFFFFF00) | (vco_rate / rate - 1);
317 writel(val, DSIPHY_PLL_CTRL(10));
318
319 return 0;
320}
321
322void dsi_setup_dividers(uint32_t val, uint32_t cfg_rcgr,
323 uint32_t cmd_rcgr)
324{
325 uint32_t i = 0;
326 uint32_t term_cnt = 5000;
327 int32_t reg;
328
329 writel(val, cfg_rcgr);
330 writel(0x1, cmd_rcgr);
331 reg = readl(cmd_rcgr);
332 while (reg & 0x1)
333 {
334 i++;
335 if (i > term_cnt)
336 {
337 dprintf(CRITICAL, "some dsi clock not enabled"
338 "exceeded polling TIMEOUT!\n");
339 break;
340 }
341 udelay(1);
342 reg = readl(cmd_rcgr);
343 }
344}
345
346void vco_enable(int enable)
347{
348 if (enable)
349 {
350 writel(0x1, DSIPHY_PLL_CTRL(0));
351 while (!(readl(DSIPHY_PLL_READY) & 0x01))
352 udelay(1);
353 } else {
354 writel(0x0, DSIPHY_PLL_CTRL(0));
355 }
356}
357
358void dsi_clock_enable(uint32_t dsiclk_rate, uint32_t byteclk_rate)
359{
360 uint32_t vcoclk_rate;
361 int ret;
362
363 ret = clk_get_set_enable("dsi_ahb_clk", 0, 1);
364 if(ret)
365 {
366 dprintf(CRITICAL, "failed to set dsi_ahb_clk ret = %d\n", ret);
367 ASSERT(0);
368 }
369
370 ret = dsi_byte_clk_set(&vcoclk_rate, byteclk_rate);
371 if(ret)
372 {
373 dprintf(CRITICAL, "failed to set byteclk ret = %d\n", ret);
374 ASSERT(0);
375 }
376
377 ret = dsi_dsi_clk_set(vcoclk_rate, dsiclk_rate);
378 if(ret)
379 {
380 dprintf(CRITICAL, "failed to set dsiclk ret = %d\n", ret);
381 ASSERT(0);
382 }
383
384 vco_enable(1);
385
386 dsi_setup_dividers(0x105, DSI_PCLK_CFG_RCGR, DSI_PCLK_CMD_RCGR);
387 dsi_setup_dividers(0x101, DSI_BYTE_CFG_RCGR, DSI_BYTE_CMD_RCGR);
388 dsi_setup_dividers(0x101, DSI_CFG_RCGR, DSI_CMD_RCGR);
389
390 ret = clk_get_set_enable("dsi_clk", 0, 1);
391 if(ret)
392 {
393 dprintf(CRITICAL, "failed to set dsi_clk ret = %d\n", ret);
394 ASSERT(0);
395 }
396
397 ret = clk_get_set_enable("dsi_byte_clk", 0, 1);
398 if(ret)
399 {
400 dprintf(CRITICAL, "failed to set dsi_byte_clk ret = %d\n", ret);
401 ASSERT(0);
402 }
403
404 ret = clk_get_set_enable("dsi_esc_clk", 0, 1);
405 if(ret)
406 {
407 dprintf(CRITICAL, "failed to set dsi_esc_clk ret = %d\n", ret);
408 ASSERT(0);
409 }
410
411 ret = clk_get_set_enable("dsi_pclk_clk", 0, 1);
412 if(ret)
413 {
414 dprintf(CRITICAL, "failed to set dsi_pclk_clk ret = %d\n", ret);
415 ASSERT(0);
416 }
417
418 ret = clk_get_set_enable("mdp_lcdc_clk" , 0, 1);
419 if(ret)
420 {
421 dprintf(CRITICAL, "failed to set mdp_lcdc_clk ret = %d\n", ret);
422 ASSERT(0);
423 }
424
425 ret = clk_get_set_enable("mdp_dsi_clk" , 0, 1);
426 if(ret)
427 {
428 dprintf(CRITICAL, "failed to set mdp_dsi_clk ret = %d\n", ret);
429 ASSERT(0);
430 }
431}
432
433void dsi_clock_disable(void)
434{
435 clk_disable(clk_get("mdp_dsi_clk"));
436 clk_disable(clk_get("mdp_lcdc_clk"));
437 clk_disable(clk_get("dsi_pclk_clk"));
438 clk_disable(clk_get("dsi_esc_clk"));
439 clk_disable(clk_get("dsi_byte_clk"));
440 clk_disable(clk_get("dsi_clk"));
441 vco_enable(0);
442 clk_disable(clk_get("dsi_ahb_clk"));
443}
Amol Jadif2139012013-08-23 18:44:10 -0700444
445
446void clock_ce_enable(uint8_t instance)
447{
448 int ret;
449 char clk_name[64];
450
451 snprintf(clk_name, 64, "ce%u_src_clk", instance);
452 ret = clk_get_set_enable(clk_name, 100000000, 1);
453 if(ret)
454 {
455 dprintf(CRITICAL, "failed to set ce_src_clk ret = %d\n", ret);
456 ASSERT(0);
457 }
458
459 snprintf(clk_name, 64, "ce%u_core_clk", instance);
460 ret = clk_get_set_enable(clk_name, 0, 1);
461 if(ret)
462 {
463 dprintf(CRITICAL, "failed to set ce_core_clk ret = %d\n", ret);
464 ASSERT(0);
465 }
466
467 snprintf(clk_name, 64, "ce%u_ahb_clk", instance);
468 ret = clk_get_set_enable(clk_name, 0, 1);
469 if(ret)
470 {
471 dprintf(CRITICAL, "failed to set ce_ahb_clk ret = %d\n", ret);
472 ASSERT(0);
473 }
474
475 snprintf(clk_name, 64, "ce%u_axi_clk", instance);
476 ret = clk_get_set_enable(clk_name, 0, 1);
477 if(ret)
478 {
479 dprintf(CRITICAL, "failed to set ce_axi_clk ret = %d\n", ret);
480 ASSERT(0);
481 }
482
483 /* Wait for 48 * #pipes cycles.
484 * This is necessary as immediately after an access control reset (boot up)
485 * or a debug re-enable, the Crypto core sequentially clears its internal
486 * pipe key storage memory. If pipe key initialization writes are attempted
487 * during this time, they may be overwritten by the internal clearing logic.
488 */
489 udelay(1);
490}
491
492void clock_ce_disable(uint8_t instance)
493{
494 struct clk *ahb_clk;
495 struct clk *cclk;
496 struct clk *axi_clk;
497 struct clk *src_clk;
498 char clk_name[64];
499
500 snprintf(clk_name, 64, "ce%u_src_clk", instance);
501 src_clk = clk_get(clk_name);
502
503 snprintf(clk_name, 64, "ce%u_ahb_clk", instance);
504 ahb_clk = clk_get(clk_name);
505
506 snprintf(clk_name, 64, "ce%u_axi_clk", instance);
507 axi_clk = clk_get(clk_name);
508
509 snprintf(clk_name, 64, "ce%u_core_clk", instance);
510 cclk = clk_get(clk_name);
511
512 clk_disable(ahb_clk);
513 clk_disable(axi_clk);
514 clk_disable(cclk);
515 clk_disable(src_clk);
516
517 /* Some delay for the clocks to stabalize. */
518 udelay(1);
519}
520
521/* Function to asynchronously reset CE.
522 * Function assumes that all the CE clocks are off.
523 */
524static void ce_async_reset(uint8_t instance)
525{
526 if (instance == 1)
527 {
528 /* Start the block reset for CE */
529 writel(1, GCC_CE1_BCR);
530
531 udelay(2);
532
533 /* Take CE block out of reset */
534 writel(0, GCC_CE1_BCR);
535
536 udelay(2);
537 }
538 else
539 {
540 dprintf(CRITICAL, "CE instance not supported instance = %d", instance);
541 ASSERT(0);
542 }
543}
544
545void clock_config_ce(uint8_t instance)
546{
547 /* Need to enable the clock before disabling since the clk_disable()
548 * has a check to default to nop when the clk_enable() is not called
549 * on that particular clock.
550 */
551 clock_ce_enable(instance);
552
553 clock_ce_disable(instance);
554
555 ce_async_reset(instance);
556
557 clock_ce_enable(instance);
558
559}