blob: e3aaec3842e4551261dc97651a008a7afb224aec [file] [log] [blame]
Aparna Mallavarapuca676882015-01-19 20:39:06 +05301/* Copyright (c) 2015, 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#include <err.h>
29#include <assert.h>
30#include <debug.h>
31#include <reg.h>
32#include <platform/timer.h>
33#include <platform/iomap.h>
34#include <mmc.h>
35#include <clock.h>
36#include <platform/clock.h>
37#include <platform.h>
38
Padmanabhan Komanduru36e609f2015-05-04 12:52:26 -070039#define MAX_LOOPS 500
40
Aparna Mallavarapuca676882015-01-19 20:39:06 +053041void hsusb_clock_init(void)
42{
Aparna Mallavarapu7b638e62015-03-26 05:51:57 +053043 int ret;
44 struct clk *iclk, *cclk;
Aparna Mallavarapuca676882015-01-19 20:39:06 +053045
Aparna Mallavarapu7b638e62015-03-26 05:51:57 +053046 ret = clk_get_set_enable("usb_iface_clk", 0, 1);
47 if(ret)
48 {
49 dprintf(CRITICAL, "failed to set usb_iface_clk ret = %d\n", ret);
50 ASSERT(0);
51 }
52
Aparna Mallavarapuf47a8682015-04-20 13:22:08 +053053 ret = clk_get_set_enable("usb_core_clk", 133330000, 1);
Aparna Mallavarapu7b638e62015-03-26 05:51:57 +053054 if(ret)
55 {
56 dprintf(CRITICAL, "failed to set usb_core_clk ret = %d\n", ret);
57 ASSERT(0);
58 }
59
60 mdelay(20);
61
62 iclk = clk_get("usb_iface_clk");
63 cclk = clk_get("usb_core_clk");
64
65 clk_disable(iclk);
66 clk_disable(cclk);
67
68 mdelay(20);
69
70 /* Start the block reset for usb */
71 writel(1, USB_HS_BCR);
72
73 mdelay(20);
74
75 /* Take usb block out of reset */
76 writel(0, USB_HS_BCR);
77
78 mdelay(20);
79
80 ret = clk_enable(iclk);
81
82 if(ret)
83 {
84 dprintf(CRITICAL, "failed to set usb_iface_clk after async ret = %d\n", ret);
85 ASSERT(0);
86 }
87
88 ret = clk_enable(cclk);
89
90 if(ret)
91 {
92 dprintf(CRITICAL, "failed to set usb_iface_clk after async ret = %d\n", ret);
93 ASSERT(0);
94 }
Aparna Mallavarapuca676882015-01-19 20:39:06 +053095}
96
97void clock_init_mmc(uint32_t interface)
98{
Aparna Mallavarapu7b638e62015-03-26 05:51:57 +053099 char clk_name[64];
100 int ret;
Aparna Mallavarapuca676882015-01-19 20:39:06 +0530101
Aparna Mallavarapu7b638e62015-03-26 05:51:57 +0530102 snprintf(clk_name, sizeof(clk_name), "sdc%u_iface_clk", interface);
103
104 /* enable interface clock */
105 ret = clk_get_set_enable(clk_name, 0, 1);
106 if(ret)
107 {
108 dprintf(CRITICAL, "failed to set sdc1_iface_clk ret = %d\n", ret);
109 ASSERT(0);
110 }
Aparna Mallavarapuca676882015-01-19 20:39:06 +0530111}
112
113/* Configure MMC clock */
114void clock_config_mmc(uint32_t interface, uint32_t freq)
115{
Aparna Mallavarapu7b638e62015-03-26 05:51:57 +0530116 int ret = 1;
117 char clk_name[64];
118
119 snprintf(clk_name, sizeof(clk_name), "sdc%u_core_clk", interface);
120
121 if(freq == MMC_CLK_400KHZ)
122 {
123 ret = clk_get_set_enable(clk_name, 400000, 1);
124 }
125 else if(freq == MMC_CLK_50MHZ)
126 {
127 ret = clk_get_set_enable(clk_name, 50000000, 1);
128 }
129 else if(freq == MMC_CLK_177MHZ)
130 {
131 ret = clk_get_set_enable(clk_name, 177770000, 1);
132 }
133 else if(freq == MMC_CLK_192MHZ)
134 {
135 ret = clk_get_set_enable(clk_name, 192000000, 1);
136 }
137 else if(freq == MMC_CLK_200MHZ)
138 {
139 ret = clk_get_set_enable(clk_name, 200000000, 1);
140 }
141 else if(freq == MMC_CLK_400MHZ)
142 {
143 ret = clk_get_set_enable(clk_name, 384000000, 1);
144 }
145 else
146 {
147 dprintf(CRITICAL, "sdc frequency (%u) is not supported\n", freq);
148 ASSERT(0);
149 }
150
151 if(ret)
152 {
153 dprintf(CRITICAL, "failed to set %s ret = %d\n", clk_name, ret);
154 ASSERT(0);
155 }
Aparna Mallavarapuca676882015-01-19 20:39:06 +0530156}
157
158/* Configure UART clock based on the UART block id*/
159void clock_config_uart_dm(uint8_t id)
160{
Aparna Mallavarapu7b638e62015-03-26 05:51:57 +0530161 int ret;
162 char iclk[64];
163 char cclk[64];
Aparna Mallavarapuca676882015-01-19 20:39:06 +0530164
Aparna Mallavarapu7b638e62015-03-26 05:51:57 +0530165 snprintf(iclk, sizeof(iclk), "uart%u_iface_clk", id);
166 snprintf(cclk, sizeof(cclk), "uart%u_core_clk", id);
167
168 ret = clk_get_set_enable(iclk, 0, 1);
169 if(ret)
170 {
171 dprintf(CRITICAL, "failed to set %s ret = %d\n", iclk, ret);
172 ASSERT(0);
173 }
174
175 ret = clk_get_set_enable(cclk, 7372800, 1);
176 if(ret)
177 {
178 dprintf(CRITICAL, "failed to set %s ret = %d\n", cclk, ret);
179 ASSERT(0);
180 }
Aparna Mallavarapuca676882015-01-19 20:39:06 +0530181}
182
Padmanabhan Komandurufba66322015-04-13 12:47:31 -0700183/* Control the MDSS GDSC */
184void mdp_gdsc_ctrl(uint8_t enable)
185{
186 uint32_t reg = 0;
187 reg = readl(MDP_GDSCR);
188 if (enable) {
189 if (!(reg & GDSC_POWER_ON_BIT)) {
190 reg &= ~(BIT(0) | GDSC_EN_FEW_WAIT_MASK);
191 reg |= GDSC_EN_FEW_WAIT_256_MASK;
192 writel(reg, MDP_GDSCR);
193 while(!(readl(MDP_GDSCR) & (GDSC_POWER_ON_BIT)));
194 } else {
195 dprintf(SPEW, "MDP GDSC already enabled\n");
196 }
197 } else {
198 reg |= BIT(0);
199 writel(reg, MDP_GDSCR);
200 while(readl(MDP_GDSCR) & (GDSC_POWER_ON_BIT));
201 }
202}
203
204/* Enable all the MDP branch clocks */
205void mdp_clock_enable(void)
206{
207 int ret;
208
209 ret = clk_get_set_enable("mdp_ahb_clk", 0, 1);
210 if(ret)
211 {
212 dprintf(CRITICAL, "failed to set mdp_ahb_clk ret = %d\n", ret);
213 ASSERT(0);
214 }
215
216 /* Set MDP clock to 320MHz */
217 ret = clk_get_set_enable("mdss_mdp_clk_src", 320000000, 1);
218
219 if(ret)
220 {
221 dprintf(CRITICAL, "failed to set mdp_clk_src ret = %d\n", ret);
222 ASSERT(0);
223 }
224
225 ret = clk_get_set_enable("mdss_vsync_clk", 0, 1);
226 if(ret)
227 {
228 dprintf(CRITICAL, "failed to set mdss vsync clk ret = %d\n", ret);
229 ASSERT(0);
230 }
231
232 ret = clk_get_set_enable("mdss_mdp_clk", 0, 1);
233 if(ret)
234 {
235 dprintf(CRITICAL, "failed to set mdp_clk ret = %d\n", ret);
236 ASSERT(0);
237 }
238}
239
240/* Disable all the MDP branch clocks */
241void mdp_clock_disable(void)
242{
243 clk_disable(clk_get("mdss_vsync_clk"));
244 clk_disable(clk_get("mdss_mdp_clk"));
245 clk_disable(clk_get("mdss_mdp_clk_src"));
246 clk_disable(clk_get("mdp_ahb_clk"));
247}
248
249/* Disable all the bus clocks needed by MDSS */
250void mdss_bus_clocks_disable(void)
251{
252 /* Disable MDSS AXI clock */
253 clk_disable(clk_get("mdss_axi_clk"));
254}
255
256/* Enable all the bus clocks needed by MDSS */
257void mdss_bus_clocks_enable(void)
258{
259 int ret;
260
261 /* Configure AXI clock */
262 ret = clk_get_set_enable("mdss_axi_clk", 0, 1);
263 if(ret)
264 {
265 dprintf(CRITICAL, "failed to set mdss_axi_clk ret = %d\n", ret);
266 ASSERT(0);
267 }
268}
269
Padmanabhan Komanduru36e609f2015-05-04 12:52:26 -0700270static void rcg_update_config(uint32_t reg)
271{
272 int i;
273
274 for (i = 0; i < MAX_LOOPS; i++) {
275 if (!(readl(reg) & BIT(0)))
276 return;
277 udelay(1);
278 }
279
280 dprintf(CRITICAL, "failed to update rcg config for reg = 0x%x\n", reg);
281 ASSERT(0);
282}
283
284static void branch_clk_halt_check(uint32_t reg)
285{
286 int i;
287
288 for (i = 0; i < MAX_LOOPS; i++) {
289 if (!(readl(reg) & BIT(31)))
290 return;
291 udelay(1);
292 }
293
294 dprintf(CRITICAL, "failed to enable branch for reg = 0x%x\n", reg);
295 ASSERT(0);
296}
297
Padmanabhan Komandurufba66322015-04-13 12:47:31 -0700298/* Disable all the branch clocks needed by the DSI controller */
Padmanabhan Komanduru82ae7132015-06-08 15:46:33 +0530299void gcc_dsi_clocks_disable(uint32_t flags)
Padmanabhan Komandurufba66322015-04-13 12:47:31 -0700300{
Padmanabhan Komanduru82ae7132015-06-08 15:46:33 +0530301 if (flags & MMSS_DSI_CLKS_FLAG_DSI0) {
302 clk_disable(clk_get("mdss_esc0_clk"));
303 writel(0x0, DSI_PIXEL0_CBCR);
304 writel(0x0, DSI_BYTE0_CBCR);
305 }
306
307 if (flags & MMSS_DSI_CLKS_FLAG_DSI1) {
308 clk_disable(clk_get("mdss_esc1_clk"));
309 writel(0x0, DSI_PIXEL1_CBCR);
310 writel(0x0, DSI_BYTE1_CBCR);
311 }
Padmanabhan Komandurufba66322015-04-13 12:47:31 -0700312}
313
314/* Configure all the branch clocks needed by the DSI controller */
Padmanabhan Komanduru82ae7132015-06-08 15:46:33 +0530315void gcc_dsi_clocks_enable(uint32_t flags, uint8_t pclk0_m,
316 uint8_t pclk0_n, uint8_t pclk0_d)
Padmanabhan Komandurufba66322015-04-13 12:47:31 -0700317{
318 int ret;
319
Padmanabhan Komanduru82ae7132015-06-08 15:46:33 +0530320 if (flags & MMSS_DSI_CLKS_FLAG_DSI0) {
321 /* Enable DSI0 branch clocks */
Padmanabhan Komandurufba66322015-04-13 12:47:31 -0700322
Padmanabhan Komanduru82ae7132015-06-08 15:46:33 +0530323 /* Set the source for DSI0 byte RCG */
324 writel(0x100, DSI_BYTE0_CFG_RCGR);
325 /* Set the update RCG bit */
326 writel(0x1, DSI_BYTE0_CMD_RCGR);
327 rcg_update_config(DSI_BYTE0_CMD_RCGR);
328 /* Enable the branch clock */
329 writel(0x1, DSI_BYTE0_CBCR);
330 branch_clk_halt_check(DSI_BYTE0_CBCR);
Padmanabhan Komandurufba66322015-04-13 12:47:31 -0700331
Padmanabhan Komanduru82ae7132015-06-08 15:46:33 +0530332 /* Configure Pixel clock */
333 /* Set the source for DSI0 pixel RCG */
334 writel(0x100, DSI_PIXEL0_CFG_RCGR);
335 /* Set the MND for DSI0 pixel clock */
336 writel(pclk0_m, DSI_PIXEL0_M);
337 writel(pclk0_n, DSI_PIXEL0_N);
338 writel(pclk0_d, DSI_PIXEL0_D);
339 /* Set the update RCG bit */
340 writel(0x1, DSI_PIXEL0_CMD_RCGR);
341 rcg_update_config(DSI_PIXEL0_CMD_RCGR);
342 /* Enable the branch clock */
343 writel(0x1, DSI_PIXEL0_CBCR);
344 branch_clk_halt_check(DSI_PIXEL0_CBCR);
345
346 /* Configure ESC clock */
347 ret = clk_get_set_enable("mdss_esc0_clk", 0, 1);
348 if (ret) {
349 dprintf(CRITICAL, "failed to set esc0_clk ret = %d\n", ret);
350 ASSERT(0);
351 }
352 }
353
354 if (flags & MMSS_DSI_CLKS_FLAG_DSI1) {
355 /* Enable DSI1 branch clocks */
356
357 /* Set the source for DSI1 byte RCG */
358 writel(0x100, DSI_BYTE1_CFG_RCGR);
359 /* Set the update RCG bit */
360 writel(0x1, DSI_BYTE1_CMD_RCGR);
361 rcg_update_config(DSI_BYTE1_CMD_RCGR);
362 /* Enable the branch clock */
363 writel(0x1, DSI_BYTE1_CBCR);
364 branch_clk_halt_check(DSI_BYTE1_CBCR);
365
366 /* Configure Pixel clock */
367 /* Set the source for DSI1 pixel RCG */
368 writel(0x100, DSI_PIXEL1_CFG_RCGR);
369 /* Set the MND for DSI1 pixel clock */
370 writel(pclk0_m, DSI_PIXEL1_M);
371 writel(pclk0_n, DSI_PIXEL1_N);
372 writel(pclk0_d, DSI_PIXEL1_D);
373 /* Set the update RCG bit */
374 writel(0x1, DSI_PIXEL1_CMD_RCGR);
375 rcg_update_config(DSI_PIXEL1_CMD_RCGR);
376 /* Enable the branch clock */
377 writel(0x1, DSI_PIXEL1_CBCR);
378 branch_clk_halt_check(DSI_PIXEL1_CBCR);
379
380 /* Configure ESC clock */
381 ret = clk_get_set_enable("mdss_esc1_clk", 0, 1);
382 if (ret) {
383 dprintf(CRITICAL, "failed to set esc1_clk ret = %d\n", ret);
384 ASSERT(0);
385 }
Padmanabhan Komandurufba66322015-04-13 12:47:31 -0700386 }
387}
388
Aparna Mallavarapuca676882015-01-19 20:39:06 +0530389/* Function to asynchronously reset CE.
390 * Function assumes that all the CE clocks are off.
391 */
392static void ce_async_reset(uint8_t instance)
393{
Aparna Mallavarapu1e8b0932015-03-29 23:38:13 +0530394 /* Start the block reset for CE */
395 writel(1, GCC_CRYPTO_BCR);
Aparna Mallavarapuca676882015-01-19 20:39:06 +0530396
Aparna Mallavarapu1e8b0932015-03-29 23:38:13 +0530397 udelay(2);
398
399 /* Take CE block out of reset */
400 writel(0, GCC_CRYPTO_BCR);
401
402 udelay(2);
Aparna Mallavarapuca676882015-01-19 20:39:06 +0530403}
404
405void clock_ce_enable(uint8_t instance)
406{
Aparna Mallavarapu1e8b0932015-03-29 23:38:13 +0530407 int ret;
408 char clk_name[64];
409
410 snprintf(clk_name, sizeof(clk_name), "ce%u_src_clk", instance);
411 ret = clk_get_set_enable(clk_name, 160000000, 1);
412 if(ret)
413 {
414 dprintf(CRITICAL, "failed to set ce%u_src_clk ret = %d\n", instance, ret);
415 ASSERT(0);
416 }
417
418 snprintf(clk_name, sizeof(clk_name), "ce%u_core_clk", instance);
419 ret = clk_get_set_enable(clk_name, 0, 1);
420 if(ret)
421 {
422 dprintf(CRITICAL, "failed to set ce%u_core_clk ret = %d\n", instance, ret);
423 ASSERT(0);
424 }
425
426 snprintf(clk_name, sizeof(clk_name), "ce%u_ahb_clk", instance);
427 ret = clk_get_set_enable(clk_name, 0, 1);
428 if(ret)
429 {
430 dprintf(CRITICAL, "failed to set ce%u_ahb_clk ret = %d\n", instance, ret);
431 ASSERT(0);
432 }
433
434 snprintf(clk_name, sizeof(clk_name), "ce%u_axi_clk", instance);
435 ret = clk_get_set_enable(clk_name, 0, 1);
436 if(ret)
437 {
438 dprintf(CRITICAL, "failed to set ce%u_axi_clk ret = %d\n", instance, ret);
439 ASSERT(0);
440 }
441
442 /* Wait for 48 * #pipes cycles.
443 * This is necessary as immediately after an access control reset (boot up)
444 * or a debug re-enable, the Crypto core sequentially clears its internal
445 * pipe key storage memory. If pipe key initialization writes are attempted
446 * during this time, they may be overwritten by the internal clearing logic.
447 */
448 udelay(1);
Aparna Mallavarapuca676882015-01-19 20:39:06 +0530449
450}
451
452void clock_ce_disable(uint8_t instance)
453{
Aparna Mallavarapu1e8b0932015-03-29 23:38:13 +0530454 struct clk *ahb_clk;
455 struct clk *cclk;
456 struct clk *axi_clk;
457 struct clk *src_clk;
458 char clk_name[64];
459
460 snprintf(clk_name, sizeof(clk_name), "ce%u_src_clk", instance);
461 src_clk = clk_get(clk_name);
462
463 snprintf(clk_name, sizeof(clk_name), "ce%u_ahb_clk", instance);
464 ahb_clk = clk_get(clk_name);
465
466 snprintf(clk_name, sizeof(clk_name), "ce%u_axi_clk", instance);
467 axi_clk = clk_get(clk_name);
468
469 snprintf(clk_name, sizeof(clk_name), "ce%u_core_clk", instance);
470 cclk = clk_get(clk_name);
471
472 clk_disable(ahb_clk);
473 clk_disable(axi_clk);
474 clk_disable(cclk);
475 clk_disable(src_clk);
476
477 /* Some delay for the clocks to stabalize. */
478 udelay(1);
Aparna Mallavarapuca676882015-01-19 20:39:06 +0530479
480}
481
482void clock_config_ce(uint8_t instance)
483{
484 /* Need to enable the clock before disabling since the clk_disable()
485 * has a check to default to nop when the clk_enable() is not called
486 * on that particular clock.
487 */
488 clock_ce_enable(instance);
489
490 clock_ce_disable(instance);
491
492 ce_async_reset(instance);
493
494 clock_ce_enable(instance);
495}