blob: 5faa147dc1b0fac12c1eb9ede0cb979cc9e0c57e [file] [log] [blame]
Joonwoo Park451dca32014-04-02 11:47:03 -07001/*
anisha agarwal35eb8032017-03-21 13:12:12 -07002 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
Joonwoo Park451dca32014-04-02 11:47:03 -07003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 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 copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
11 * * Neither the name of Linux Foundation nor
12 * the names of its contributors may be used to endorse or promote
13 * products derived from this software without specific prior written
14 * permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * 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 <clock.h>
34#include <mmc.h>
35#include <platform/clock.h>
36#include <platform/iomap.h>
37#include <platform/timer.h>
Channagoud Kadabifdfee232015-10-07 11:55:47 -070038#include <platform.h>
vijay kumar7d06bbb2015-11-24 13:04:55 +053039#include <rpm-smd.h>
40#include <regulator.h>
41
42#define RPM_CE_CLK_TYPE 0x6563
43#define CE1_CLK_ID 0x0
44#define RPM_SMD_KEY_RATE 0x007A484B
45
46uint32_t CE1_CLK[][8]=
47{
48 {
49 RPM_CE_CLK_TYPE, CE1_CLK_ID,
50 KEY_SOFTWARE_ENABLE, 4, GENERIC_DISABLE,
51 RPM_SMD_KEY_RATE, 4, 0,
52 },
53 {
54 RPM_CE_CLK_TYPE, CE1_CLK_ID,
55 KEY_SOFTWARE_ENABLE, 4, GENERIC_ENABLE,
56 RPM_SMD_KEY_RATE, 4, 171430, /* clk rate in KHZ */
57 },
58};
Joonwoo Park451dca32014-04-02 11:47:03 -070059
60void clock_config_uart_dm(uint8_t id)
61{
62 int ret;
63 char clk_name[64];
64
65 snprintf(clk_name, sizeof(clk_name), "uart%u_iface_clk", id);
66 ret = clk_get_set_enable(clk_name, 0, 1);
67 if (ret)
68 {
69 dprintf(CRITICAL, "failed to set %s ret = %d\n", clk_name, ret);
70 ASSERT(0);
71 }
72
73 snprintf(clk_name, sizeof(clk_name), "uart%u_core_clk", id);
74 ret = clk_get_set_enable(clk_name, 7372800, 1);
75 if (ret)
76 {
77 dprintf(CRITICAL, "failed to set %s ret = %d\n", clk_name, ret);
78 ASSERT(0);
79 }
80}
81
82/*
83 * Disable power collapse using GDSCR:
84 * Globally Distributed Switch Controller Register
85 */
86void clock_usb30_gdsc_enable(void)
87{
88 uint32_t reg = readl(GCC_USB30_GDSCR);
89
90 reg &= ~(0x1);
91
92 writel(reg, GCC_USB30_GDSCR);
93}
94
95/* enables usb30 clocks */
96void clock_usb30_init(void)
97{
98 int ret;
99
100 ret = clk_get_set_enable("usb30_iface_clk", 0, 1);
101 if(ret)
102 {
103 dprintf(CRITICAL, "failed to set usb30_iface_clk. ret = %d\n", ret);
104 ASSERT(0);
105 }
106
107 clock_usb30_gdsc_enable();
108
anisha agarwal35eb8032017-03-21 13:12:12 -0700109 if (platform_is_sdx20())
110 ret = clk_get_set_enable("usb30_master_clk_sdx20", 200000000, 1);
Runmin Wangdc8e9732016-10-06 11:14:08 -0700111 else
112 ret = clk_get_set_enable("usb30_master_clk", 125000000, 1);
Joonwoo Park451dca32014-04-02 11:47:03 -0700113 if(ret)
114 {
115 dprintf(CRITICAL, "failed to set usb30_master_clk. ret = %d\n", ret);
116 ASSERT(0);
117 }
118
Karthik Jadala8e6b2192017-02-08 12:59:16 +0530119 if (platform_is_mdm9650())
120 ret = clk_get_set_enable("usb30_pipe_clk_mdm9650", 0, 1);
anisha agarwal35eb8032017-03-21 13:12:12 -0700121 else if (platform_is_sdx20())
122 ret = clk_get_set_enable("usb30_pipe_clk_sdx20", 0, 1);
Channagoud Kadabifdfee232015-10-07 11:55:47 -0700123 else
124 ret = clk_get_set_enable("usb30_pipe_clk", 19200000, 1);
125
Joonwoo Park451dca32014-04-02 11:47:03 -0700126 if(ret)
127 {
128 dprintf(CRITICAL, "failed to set usb30_pipe_clk. ret = %d\n", ret);
129 ASSERT(0);
130 }
131
132 ret = clk_get_set_enable("usb30_aux_clk", 1000000, 1);
133 if(ret)
134 {
135 dprintf(CRITICAL, "failed to set usb30_aux_clk. ret = %d\n", ret);
136 ASSERT(0);
137 }
138
anisha agarwal35eb8032017-03-21 13:12:12 -0700139 if (platform_is_sdx20())
140 ret = clk_get_set_enable("usb30_mock_utmi_clk_sdx20", 19200000, 1);
Runmin Wangdc8e9732016-10-06 11:14:08 -0700141 else
142 ret = clk_get_set_enable("usb30_mock_utmi_clk", 60000000, true);
Channagoud Kadabifdfee232015-10-07 11:55:47 -0700143 if(ret)
144 {
145 dprintf(CRITICAL, "failed to set usb30_mock_utmi_clk ret = %d\n", ret);
146 ASSERT(0);
147 }
148
149 ret = clk_get_set_enable("usb30_sleep_clk", 0, true);
150 if(ret)
151 {
152 dprintf(CRITICAL, "failed to set usb30_sleep_clk ret = %d\n", ret);
153 ASSERT(0);
154 }
155
Joonwoo Park451dca32014-04-02 11:47:03 -0700156 ret = clk_get_set_enable("usb_phy_cfg_ahb_clk", 0, 1);
157 if(ret)
158 {
159 dprintf(CRITICAL, "failed to set usb_phy_cfg_ahb_clk ret = %d\n", ret);
160 ASSERT(0);
161 }
162}
163
164void clock_init_mmc(uint32_t interface)
165{
166 char clk_name[64];
167 int ret;
168
169 snprintf(clk_name, sizeof(clk_name), "sdc%u_iface_clk", interface);
170
171 /* enable interface clock */
172 ret = clk_get_set_enable(clk_name, 0, 1);
173 if(ret)
174 {
175 dprintf(CRITICAL, "failed to set sdc1_iface_clk ret = %d\n", ret);
176 ASSERT(0);
177 }
178}
179
180/* Configure MMC clock */
181void clock_config_mmc(uint32_t interface, uint32_t freq)
182{
Sridhar Parasuram673c6bb2014-12-29 13:39:35 -0800183 int ret = 0;
Joonwoo Park451dca32014-04-02 11:47:03 -0700184 char clk_name[64];
185
anisha agarwal35eb8032017-03-21 13:12:12 -0700186 if(platform_is_sdx20())
187 snprintf(clk_name, sizeof(clk_name), "sdc%u_core_clk_sdx20", interface);
Runmin Wangdc8e9732016-10-06 11:14:08 -0700188 else
189 snprintf(clk_name, sizeof(clk_name), "sdc%u_core_clk", interface);
Joonwoo Park451dca32014-04-02 11:47:03 -0700190
191 if(freq == MMC_CLK_400KHZ)
192 {
193 ret = clk_get_set_enable(clk_name, 400000, 1);
194 }
195 else if(freq == MMC_CLK_50MHZ)
196 {
197 ret = clk_get_set_enable(clk_name, 50000000, 1);
198 }
199 else if(freq == MMC_CLK_200MHZ)
200 {
201 ret = clk_get_set_enable(clk_name, 200000000, 1);
202 }
Channagoud Kadabi6608d022015-04-20 11:31:56 -0700203 else if(freq == MMC_CLK_171MHZ)
Joonwoo Park451dca32014-04-02 11:47:03 -0700204 {
Channagoud Kadabi6608d022015-04-20 11:31:56 -0700205 ret = clk_get_set_enable(clk_name, 171430000, 1);
Joonwoo Park451dca32014-04-02 11:47:03 -0700206 }
207 else
208 {
209 dprintf(CRITICAL, "sdc frequency (%u) is not supported\n", freq);
210 ASSERT(0);
211 }
212
213 if(ret)
214 {
215 dprintf(CRITICAL, "failed to set %s ret = %d\n", clk_name, ret);
216 ASSERT(0);
217 }
218}
219
220void clock_bumpup_pipe3_clk()
221{
Channagoud Kadabifdfee232015-10-07 11:55:47 -0700222 int ret =0;
Joonwoo Park451dca32014-04-02 11:47:03 -0700223
Karthik Jadala8e6b2192017-02-08 12:59:16 +0530224 if (platform_is_mdm9650())
Channagoud Kadabifdfee232015-10-07 11:55:47 -0700225 ret = clk_get_set_enable("usb30_pipe_clk", 0, true);
226 else
227 ret = clk_get_set_enable("usb30_pipe_clk", 125000000, true);
228
Joonwoo Park451dca32014-04-02 11:47:03 -0700229 if(ret)
230 {
231 dprintf(CRITICAL, "failed to set usb30_pipe_clk. ret = %d\n", ret);
232 ASSERT(0);
233 }
234}
Channagoud Kadabifdfee232015-10-07 11:55:47 -0700235
Runmin Wangdc8e9732016-10-06 11:14:08 -0700236/*
237 * This is the clock reset function for USB3
238 */
Channagoud Kadabifdfee232015-10-07 11:55:47 -0700239void clock_reset_usb_phy()
240{
241 int ret;
242
243 struct clk *phy_reset_clk = NULL;
244 struct clk *pipe_reset_clk = NULL;
245 struct clk *master_clk = NULL;
246
247 master_clk = clk_get("usb30_master_clk");
248 ASSERT(master_clk);
249
250 /* Look if phy com clock is present */
251 phy_reset_clk = clk_get("usb30_phy_reset");
252 ASSERT(phy_reset_clk);
253
anisha agarwal35eb8032017-03-21 13:12:12 -0700254 if(platform_is_sdx20()){
255 pipe_reset_clk = clk_get("usb30_pipe_clk_sdx20");
Runmin Wangdc8e9732016-10-06 11:14:08 -0700256 ASSERT(pipe_reset_clk);
257 }
258 else{
259 pipe_reset_clk = clk_get("usb30_pipe_clk");
260 ASSERT(pipe_reset_clk);
261 }
Channagoud Kadabifdfee232015-10-07 11:55:47 -0700262
263 /* ASSERT */
264 ret = clk_reset(master_clk, CLK_RESET_ASSERT);
265 if (ret)
266 {
267 dprintf(CRITICAL, "Failed to assert usb30_master_reset clk\n");
268 return;
269 }
270 ret = clk_reset(phy_reset_clk, CLK_RESET_ASSERT);
271
272 if (ret)
273 {
274 dprintf(CRITICAL, "Failed to assert usb30_phy_reset clk\n");
275 goto deassert_master_clk;
276 }
277
278 ret = clk_reset(pipe_reset_clk, CLK_RESET_ASSERT);
279 if (ret)
280 {
281 dprintf(CRITICAL, "Failed to assert usb30_pipe_clk\n");
282 goto deassert_phy_clk;
283 }
284
285 udelay(100);
286
287 /* DEASSERT */
288 ret = clk_reset(pipe_reset_clk, CLK_RESET_DEASSERT);
289 if (ret)
290 {
291 dprintf(CRITICAL, "Failed to deassert usb_pipe_clk\n");
292 return;
293 }
294
295deassert_phy_clk:
296
297 ret = clk_reset(phy_reset_clk, CLK_RESET_DEASSERT);
298 if (ret)
299 {
300 dprintf(CRITICAL, "Failed to deassert usb30_phy_com_reset clk\n");
301 return;
302 }
303deassert_master_clk:
304
305 ret = clk_reset(master_clk, CLK_RESET_DEASSERT);
306 if (ret)
307 {
308 dprintf(CRITICAL, "Failed to deassert usb30_master clk\n");
309 return;
310 }
311
312}
vijay kumar7d06bbb2015-11-24 13:04:55 +0530313
314void clock_ce_enable(uint8_t instance)
315{
316 int ret;
317 char clk_name[64];
318
Karthik Jadala8e6b2192017-02-08 12:59:16 +0530319 if (platform_is_mdm9650())
vijay kumar7d06bbb2015-11-24 13:04:55 +0530320 {
321 if (instance == 1)
322 rpm_send_data(&CE1_CLK[GENERIC_ENABLE][0], 24, RPM_REQUEST_TYPE);
323 else
324 {
325 dprintf(CRITICAL, "Unsupported CE instance\n");
326 ASSERT(0);
327 }
328 return;
329 }
330
331 snprintf(clk_name, sizeof(clk_name), "ce%u_src_clk", instance);
332 ret = clk_get_set_enable(clk_name, 160000000, 1);
333 if(ret)
334 {
335 dprintf(CRITICAL, "failed to set ce%u_src_clk ret = %d\n", instance, ret);
336 ASSERT(0);
337 }
338
339 snprintf(clk_name, sizeof(clk_name), "ce%u_core_clk", instance);
340 ret = clk_get_set_enable(clk_name, 0, 1);
341 if(ret)
342 {
343 dprintf(CRITICAL, "failed to set ce%u_core_clk ret = %d\n", instance, ret);
344 ASSERT(0);
345 }
346
347 snprintf(clk_name, sizeof(clk_name), "ce%u_ahb_clk", instance);
348 ret = clk_get_set_enable(clk_name, 0, 1);
349 if(ret)
350 {
351 dprintf(CRITICAL, "failed to set ce%u_ahb_clk ret = %d\n", instance, ret);
352 ASSERT(0);
353 }
354
355 snprintf(clk_name, sizeof(clk_name), "ce%u_axi_clk", instance);
356 ret = clk_get_set_enable(clk_name, 0, 1);
357 if(ret)
358 {
359 dprintf(CRITICAL, "failed to set ce%u_axi_clk ret = %d\n", instance, ret);
360 ASSERT(0);
361 }
362
363 /* Wait for 48 * #pipes cycles.
364 * This is necessary as immediately after an access control reset (boot up)
365 * or a debug re-enable, the Crypto core sequentially clears its internal
366 * pipe key storage memory. If pipe key initialization writes are attempted
367 * during this time, they may be overwritten by the internal clearing logic.
368 */
369 udelay(1);
370}
371
372void clock_ce_disable(uint8_t instance)
373{
374 struct clk *ahb_clk;
375 struct clk *cclk;
376 struct clk *axi_clk;
377 struct clk *src_clk;
378 char clk_name[64];
379
Karthik Jadala8e6b2192017-02-08 12:59:16 +0530380 if (platform_is_mdm9650())
vijay kumar7d06bbb2015-11-24 13:04:55 +0530381 {
382 if (instance == 1)
383 rpm_send_data(&CE1_CLK[GENERIC_DISABLE][0], 24, RPM_REQUEST_TYPE);
384 else
385 {
386 dprintf(CRITICAL, "Unsupported CE instance\n");
387 ASSERT(0);
388 }
389 return;
390 }
391
392 snprintf(clk_name, sizeof(clk_name), "ce%u_src_clk", instance);
393 src_clk = clk_get(clk_name);
394
395 snprintf(clk_name, sizeof(clk_name), "ce%u_ahb_clk", instance);
396 ahb_clk = clk_get(clk_name);
397
398 snprintf(clk_name, sizeof(clk_name), "ce%u_axi_clk", instance);
399 axi_clk = clk_get(clk_name);
400
401 snprintf(clk_name, sizeof(clk_name), "ce%u_core_clk", instance);
402 cclk = clk_get(clk_name);
403
404 clk_disable(ahb_clk);
405 clk_disable(axi_clk);
406 clk_disable(cclk);
407 clk_disable(src_clk);
408
409 /* Some delay for the clocks to stabalize. */
410 udelay(1);
411}
412/* Function to asynchronously reset CE.
413 * Function assumes that all the CE clocks are off.
414 */
415static void ce_async_reset(uint8_t instance)
416{
417 /* Start the block reset for CE */
418 writel(1, GCC_CRYPTO_BCR);
419
420 udelay(2);
421
422 /* Take CE block out of reset */
423 writel(0, GCC_CRYPTO_BCR);
424
425 udelay(2);
426}
427
428void clock_config_ce(uint8_t instance)
429{
430 /* Need to enable the clock before disabling since the clk_disable()
431 * has a check to default to nop when the clk_enable() is not called
432 * on that particular clock.
433 */
434 clock_ce_enable(instance);
435
436 clock_ce_disable(instance);
437
438 ce_async_reset(instance);
439
440 clock_ce_enable(instance);
441}