blob: baf9192818045b44ef98f84e0193b5d83636f936 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2 * (C) Copyright 2012
3 * Marvell Semiconductor <www.marvell.com>
4 * Written-by:
5 * Zhoujie Wu <zjwu@marvell.com>
6 * Qiming Wu <wuqm@marvell.com>
7 * Lu Cao <lucao@marvell.com>
8 *
9 * SPDX-License-Identifier: GPL-2.0+
10 */
11
12#include <errno.h>
13#include <common.h>
14#include <command.h>
15#include <asm/arch/cpu.h>
16#include <asm/io.h>
17#include <asm/gpio.h>
18#include <linux/list.h>
19#include <i2c.h>
20#include <power/pmic.h>
21#include <power/marvell88pm_pmic.h>
22DECLARE_GLOBAL_DATA_PTR;
23
24#define APMU_BASE 0xD4282800
25#define APMU_REG(x) (APMU_BASE + x)
26#define MPMU_BASE 0xD4050000
27#define MPMU_REG(x) (MPMU_BASE + x)
28#define APB_SPARE_BASE 0xD4090000
29#define APB_SPARE_REG(x) (APB_SPARE_BASE + x)
30#define CIU_BASE 0xD4282C00
31#define CIU_REG(x) (CIU_BASE + x)
32#define GEU_BASE 0xD4292800
33#define GEU_REG(x) (GEU_BASE + x)
34
35/* PLL */
36#define MPMU_PLL2CR MPMU_REG(0x0034)
37#define MPMU_PLL3CR MPMU_REG(0x001c)
38#define MPMU_PLL4CR MPMU_REG(0x0050)
39#define APB_SPARE_PLL2CR APB_SPARE_REG(0x104)
40#define APB_SPARE_PLL3CR APB_SPARE_REG(0x108)
41#define APB_SPARE_PLL4CR APB_SPARE_REG(0x124)
42#define APB_PLL2_SSC_CTRL APB_SPARE_REG(0x130)
43#define APB_PLL2_SSC_CONF APB_SPARE_REG(0x134)
44#define APB_PLL2_FREQOFFSET_CTRL APB_SPARE_REG(0x138)
45#define APB_PLL3_SSC_CTRL APB_SPARE_REG(0x13c)
46#define APB_PLL3_SSC_CONF APB_SPARE_REG(0x140)
47#define APB_PLL3_FREQOFFSET_CTRL APB_SPARE_REG(0x144)
48#define APB_PLL4_SSC_CTRL APB_SPARE_REG(0x148)
49#define APB_PLL4_SSC_CONF APB_SPARE_REG(0x14c)
50#define APB_PLL4_FREQOFFSET_CTRL APB_SPARE_REG(0x150)
51#define MPMU_POSR MPMU_REG(0x0010)
52#define POSR_PLL2_LOCK (1 << 29)
53#define POSR_PLL3_LOCK (1 << 30)
54#define POSR_PLL4_LOCK (1 << 31)
55
56/* FC */
57#define APMU_CP_CCR APMU_REG(0x0000)
58#define APMU_CCR APMU_REG(0x0004)
59#define APMU_CCSR APMU_REG(0x000c)
60
61#define APMU_IMR APMU_REG(0x0098)
62#define APMU_ISR APMU_REG(0x00a0)
63#define APMU_PLL_SEL_STATUS APMU_REG(0x00c4)
64#define APMU_MC_HW_SLP_TYPE APMU_REG(0x00b0)
65
66#define APMU_CC2R APMU_REG(0x0100)
67#define APMU_CC2SR APMU_REG(0x0104)
68
69#define MPMU_FCCR MPMU_REG(0x0008)
70#define MPMU_FCAP MPMU_REG(0x0054)
71#define MPMU_FCCP MPMU_REG(0x0058)
72#define MPMU_FCDCLK MPMU_REG(0x005c)
73#define MPMU_FCACLK MPMU_REG(0x0060)
74
75/* HW DFC */
76#define DVC_DFC_DEBUG APMU_REG(0x140)
77#define DFC_AP APMU_REG(0x180)
78#define DFC_CP APMU_REG(0x184)
79#define DFC_STATUS APMU_REG(0x188)
80#define DFC_LEVEL(i) APMU_REG(0x190 + ((i) << 2))
81
82/* clock gating */
83#define MC_CONF CIU_REG(0x40)
84#define APMU_MCK4_CTRL APMU_REG(0x0e8)
85
86/* core WTC/RTC */
87#define CIU_CA9_CPU_CONF_SRAM_0 CIU_REG(0x00c8)
88#define CIU_CA9_CPU_CONF_SRAM_1 CIU_REG(0x00cc)
89
90/* FUSE */
91#define APMU_GEU APMU_REG(0x068)
92#define MANU_PARA_31_00 GEU_REG(0x110)
93#define MANU_PARA_63_32 GEU_REG(0x114)
94#define MANU_PARA_95_64 GEU_REG(0x118)
95#define BLOCK4_PARA_31_00 GEU_REG(0x2B4)
96#define BLOCK0_224_255 GEU_REG(0x11c)
97#define UID_H_32 GEU_REG(0x18c)
98#define UID_L_32 GEU_REG(0x1a8)
99
100/*
101 * for ana_grp PU_CLK contro. Must be enabled if
102 * PLL2 or PLL3 or USB are used
103 */
104#define UTMI_CTRL 0xD4207104
105
106#define AP_SRC_SEL_MASK 0x7
107#define MPMU_FCAP_MASK 0x7
108#define MPMU_FCDCLK_MASK 0x7
109#define MPMU_FCACLK_MASK 0x3
110#define UNDEF_OP -1
111#define MHZ (1000 * 1000)
112#define MHZ_TO_KHZ (1000)
113
114#define PROFILE_NUM 11
115
116#define PLL_VCO_MIN (1200)
117#define PLL_VCO_MAX (3000)
118
119union pmum_pll2cr {
120 struct {
121 unsigned int reserved0:6;
122 unsigned int reserved1:2;
123 unsigned int en:1;
124 unsigned int ctrl:1;
125 unsigned int pll2fbd:9;
126 unsigned int pll2refd:5;
127 unsigned int reserved2:8;
128 } b;
129 unsigned int v;
130};
131
132union pmum_pllxcr {
133 struct {
134 unsigned int pllrefd:5;
135 unsigned int pllfbd:9;
136 unsigned int reserved0:5;
137 unsigned int pll_pu:1;
138 unsigned int reserved1:12;
139 } b;
140 unsigned int v;
141};
142
143union apb_spare_pllswcr {
144 struct {
145 unsigned int avvd1815_sel:1;
146 unsigned int vddm:2;
147 unsigned int vddl:3;
148 unsigned int icp:4;
149 unsigned int pll_bw_sel:1;
150 unsigned int kvco:4;
151 unsigned int ctune:2;
152 unsigned int divseldiff:3;
153 unsigned int divselse:3;
154 unsigned int diffclken:1;
155 unsigned int bypassen:1;
156 unsigned int gatectl:1;
157 unsigned int fd:3;
158 unsigned int reserved:3;
159 } b;
160 unsigned int v;
161};
162
163union pmum_posr {
164 struct {
165 unsigned int pll1fbd:9;
166 unsigned int pll1refd:5;
167 unsigned int pll2fbd:9;
168 unsigned int pll2refd:5;
169 unsigned int pll1_lock:1;
170 unsigned int pll2_lock:1;
171 unsigned int pll3_lock:1;
172 unsigned int pll4_lock:1;
173 } b;
174 unsigned int v;
175};
176
177union pmum_fccr {
178 struct {
179 unsigned int pll1fbd:9;
180 unsigned int pll1refd:5;
181 unsigned int pll1cen:1;
182 unsigned int mfc:1;
183 unsigned int reserved0:12;
184 unsigned int i2sclksel:1;
185 unsigned int reserved1:3;
186 } b;
187 unsigned int v;
188};
189
190union pmua_pllsel {
191 struct {
192 unsigned int cpclksel:2;
193 unsigned int apclksel1:2;
194 unsigned int ddrclksel1:2;
195 unsigned int axiclksel:2;
196 unsigned int apclksel2:1;
197 unsigned int ddrclksel2:1;
198 unsigned int reserved0:22;
199 } b;
200 unsigned int v;
201};
202
203union pmua_cc {
204 struct {
205 unsigned int core_clk_div:3;
206 unsigned int reserved0:9;
207 unsigned int ddr_clk_div:3;
208 unsigned int bus_clk_div:3;
209 unsigned int async1:1;
210 unsigned int async2:1;
211 unsigned int async3:1;
212 unsigned int async3_1:1;
213 unsigned int async4:1;
214 unsigned int async5:1;
215 unsigned int core_freq_chg_req:1;
216 unsigned int ddr_freq_chg_req:1;
217 unsigned int bus_freq_chg_req:1;
218 unsigned int core_allow_spd_chg:1;
219 unsigned int core_dyn_fc:1;
220 unsigned int dclk_dyn_fc:1;
221 unsigned int aclk_dyn_fc:1;
222 unsigned int core_rd_st_clear:1;
223 } b;
224 unsigned int v;
225};
226
227union pmua_cc_ap {
228 struct {
229 unsigned int core_clk_div:3;
230 unsigned int bus_mc_clk_div:3;
231 unsigned int biu_clk_div:3;
232 unsigned int l2_clk_div:3;
233 unsigned int ddr_clk_div:3;
234 unsigned int bus_clk_div:3;
235 unsigned int async1:1;
236 unsigned int async2:1;
237 unsigned int async3:1;
238 unsigned int async3_1:1;
239 unsigned int async4:1;
240 unsigned int async5:1;
241 unsigned int core_freq_chg_req:1;
242 unsigned int ddr_freq_chg_req:1;
243 unsigned int bus_freq_chg_req:1;
244 unsigned int core_allow_spd_chg:1;
245 unsigned int core_dyn_fc:1;
246 unsigned int dclk_dyn_fc:1;
247 unsigned int aclk_dyn_fc:1;
248 unsigned int core_rd_st_clear:1;
249 } b;
250 unsigned int v;
251};
252
253union pmua_cc2 {
254 struct {
255 unsigned int peri_clk_div:3;
256 unsigned int peri_clk_dis:1;
257 unsigned int reserved0:12;
258 unsigned int cpu0_core_rst:1;
259 unsigned int reserved1:1;
260 unsigned int cpu0_dbg_rst:1;
261 unsigned int cpu0_wdt_rst:1;
262 unsigned int cpu1_core_rst:1;
263 unsigned int reserved2:1;
264 unsigned int cpu1_dbg_rst:1;
265 unsigned int cpu1_wdt_rst:1;
266 unsigned int reserved3:8;
267 } b;
268 unsigned int v;
269};
270
271union pmua_dm_cc {
272 struct {
273 unsigned int core_clk_div:3;
274 unsigned int bus_mc_clk_div:3;
275 unsigned int biu_clk_div:3;
276 unsigned int l2_clk_div:3;
277 unsigned int ddr_clk_div:3;
278 unsigned int bus_clk_div:3;
279 unsigned int async1:1;
280 unsigned int async2:1;
281 unsigned int async3:1;
282 unsigned int async3_1:1;
283 unsigned int async4:1;
284 unsigned int async5:1;
285 unsigned int cp_rd_status:1;
286 unsigned int ap_rd_status:1;
287 unsigned int cp_fc_done:1;
288 unsigned int ap_fc_done:1;
289 unsigned int dclk_fc_done:1;
290 unsigned int aclk_fc_done:1;
291 unsigned int reserved:2;
292 } b;
293 unsigned int v;
294};
295
296union pmua_dm_cc2 {
297 struct {
298 unsigned int peri_clk_div:3;
299 unsigned int reserved:29;
300 } b;
301 unsigned int v;
302};
303
304/* HW DFC register defination */
305union dfc_level_reg {
306 struct {
307 unsigned int dclksel:3;
308 unsigned int clk_mode:1;
309 unsigned int ddr_clk_div:3;
310 unsigned int mc_table_num:5;
311 unsigned int volt_level:3;
312 unsigned int reserved:17;
313 } b;
314 unsigned int v;
315};
316
317union dfc_ap {
318 struct {
319 unsigned int dfc_req:1;
320 unsigned int freq_level:3;
321 unsigned int reserved:28;
322 } b;
323 unsigned int v;
324};
325
326union dfc_status {
327 struct {
328 unsigned int dfc_status:1;
329 unsigned int cfl:3;
330 unsigned int tfl:3;
331 unsigned int dfc_cause:2;
332 unsigned int reserved:23;
333 } b;
334 unsigned int v;
335};
336
337union apb_pllx_ssc_ctrl {
338 struct {
339 unsigned int pi_en:1;
340 unsigned int reset_pi:1;
341 unsigned int ssc_mode:1;
342 unsigned int ssc_clk_en:1;
343 unsigned int reset_ssc:1;
344 unsigned int pi_loop_mode:1;
345 unsigned int clk_det_en:1;
346 unsigned int reserved:9;
347 unsigned int intpi:4;
348 unsigned int intpr:3;
349 unsigned int reserven_in:9;
350 } b;
351 unsigned int v;
352};
353
354union apb_pllx_ssc_conf {
355 struct {
356 unsigned int ssc_rnge:11;
357 unsigned int reserved:5;
358 unsigned int ssc_freq_div:16;
359 } b;
360 unsigned int v;
361};
362
363union apb_pllx_freqoffset_ctrl {
364 struct {
365 unsigned int freq_offset_en:1;
366 unsigned int freq_offset_valid:1;
367 unsigned int freq_offset:17;
368 unsigned int reserve_in:4;
369 unsigned int reserved:9;
370 } b;
371 unsigned int v;
372};
373
374enum pll {
375 PLL2 = 0x2,
376 PLL3 = 0x3,
377 PLL4 = 0x4,
378 PLL_MAX,
379};
380
381/*
382 * AP clock source:
383 * 0x0 = PLL1 624 MHz
384 * 0x1 = PLL1 1248 MHz or PLL3_CLKOUT
385 * (depending on FCAP[2])
386 * 0x2 = PLL2_CLKOUT
387 * 0x3 = PLL1 832 MHZ
388 * 0x5 = PLL3_CLKOUTP
389 */
390enum ap_clk_sel {
391 AP_CLK_SRC_PLL1_624 = 0x0,
392 AP_CLK_SRC_PLL1_1248 = 0x1,
393 AP_CLK_SRC_PLL2 = 0x2,
394 AP_CLK_SRC_PLL1_832 = 0x3,
395 AP_CLK_SRC_PLL3P = 0x5,
396};
397
398/*
399 * DDR clock source:
400 * 0x0 = PLL1 624 MHz
401 * 0x1 = PLL1 832 MHz
402 * 0x4 = PLL2_CLKOUT
403 * 0x5 = PLL4_CLKOUT
404 * 0x6 = PLL3_CLKOUTP
405 */
406enum ddr_clk_sel {
407 DDR_CLK_SRC_PLL1_624 = 0x0,
408 DDR_CLK_SRC_PLL1_832 = 0x1,
409 DDR_CLK_SRC_PLL2 = 0x4,
410 DDR_CLK_SRC_PLL4 = 0x5,
411 DDR_CLK_SRC_PLL3P = 0x6,
412};
413
414/*
415 * AXI clock source:
416 * 0x0 = PLL1 416 MHz
417 * 0x1 = PLL1 624 MHz
418 * 0x2 = PLL2_CLKOUT
419 * 0x3 = PLL2_CLKOUTP
420 */
421enum axi_clk_sel {
422 AXI_CLK_SRC_PLL1_416 = 0x0,
423 AXI_CLK_SRC_PLL1_624 = 0x1,
424 AXI_CLK_SRC_PLL2 = 0x2,
425 AXI_CLK_SRC_PLL2P = 0x3,
426};
427
428enum ddr_type {
429 DDR_400M = 0,
430 DDR_533M,
431 DDR_667M,
432 DDR_800M,
433 DDR_TYPE_MAX,
434};
435
436enum ssc_mode {
437 CENTER_SPREAD = 0x0,
438 DOWN_SPREAD = 0x1,
439};
440
441struct pll_post_div {
442 unsigned int div; /* PLL divider value */
443 unsigned int divselval; /* PLL corresonding reg setting */
444};
445
446/* RTC/WTC table used for solution change rtc/wtc on the fly */
447struct cpu_rtcwtc {
448 /* max rate could be used by this rtc/wtc */
449 unsigned int max_pclk;
450 unsigned int l1_rtc;
451 unsigned int l2_rtc;
452};
453
454struct cpu_opt {
455 unsigned int pclk; /* core clock */
456 unsigned int l2clk; /* L2 cache interface clock */
457 unsigned int pdclk; /* DDR interface clock */
458 unsigned int baclk; /* bus interface clock */
459 unsigned int periphclk; /* PERIPHCLK */
460 enum ap_clk_sel ap_clk_sel; /* core src sel val */
461 unsigned int ap_clk_src; /* core src rate */
462 unsigned int pclk_div; /* core clk divider*/
463 unsigned int l2clk_div; /* L2 clock divider */
464 unsigned int pdclk_div; /* DDR interface clock divider */
465 unsigned int baclk_div; /* bus interface clock divider */
466 unsigned int periphclk_div; /* PERIPHCLK divider */
467 unsigned int l1_rtc; /* L1 cache RTC/WTC */
468 unsigned int l2_rtc; /* L2 cache RTC/WTC */
469 struct list_head node;
470
471 /* use to record voltage requirement(mV) */
472 unsigned int volts;
473};
474
475struct ddr_opt {
476 unsigned int dclk; /* ddr clock */
477 unsigned int ddr_tbl_index; /* ddr FC table index */
478 unsigned int ddr_freq_level; /* ddr freq level(0~7) */
479 enum ddr_clk_sel ddr_clk_sel;/* ddr src sel val */
480 unsigned int ddr_clk_src; /* ddr src rate */
481 unsigned int dclk_div; /* ddr clk divider */
482
483 /* use to record voltage requirement(mV) */
484 unsigned int volts;
485};
486
487struct axi_opt {
488 unsigned int aclk; /* axi clock */
489 enum axi_clk_sel axi_clk_sel;/* axi src sel val */
490 unsigned int axi_clk_src; /* axi src rate */
491 unsigned int aclk_div; /* axi clk divider */
492
493 /* use to record voltage requirement(mV) */
494 unsigned int volts;
495};
496
497/* comp that voting for vcore in uboot */
498enum vcore_comps {
499 CORE = 0,
500 DDR,
501 AXI,
502 VM_RAIL_MAX,
503};
504
505/* vcore levels */
506enum vcore_lvls {
507 VL0 = 0,
508 VL1,
509 VL2,
510 VL3,
511 VL_MAX,
512};
513
514/*
515 * used to show the bind relationship of cpu,ddr,axi
516 * only used when core,ddr,axi FC bind together
517 */
518struct operating_point {
519 u32 pclk;
520 u32 dclk;
521 u32 aclk;
522 u32 vcore;
523};
524
525struct platform_opt {
526 unsigned int cpuid;
527 unsigned int chipid;
528 char *cpu_name;
529 enum ddr_type ddrtype;
530 struct operating_point *op_array;
531 unsigned int com_op_size;
532 struct cpu_opt *cpu_opt;
533 unsigned int cpu_opt_size;
534 struct ddr_opt *ddr_opt;
535 unsigned int ddr_opt_size;
536 struct axi_opt *axi_opt;
537 unsigned int axi_opt_size;
538 /* pll2 pll3 pll4 freq used on this platform */
539 unsigned int pll2vcofreq;
540 unsigned int pll2freq;
541 unsigned int pll2pfreq;
542 unsigned int pll3vcofreq;
543 unsigned int pll3freq;
544 unsigned int pll3pfreq;
545 unsigned int pll4vcofreq;
546 unsigned int pll4freq;
547 unsigned int pll4pfreq;
548 /* the default max cpu rate could be supported */
549 unsigned int df_max_cpurate;
550 /* the plat rule for filter core ops */
551 unsigned int (*is_cpuop_invalid_plt)(struct cpu_opt *cop);
552
553 /* dvfs related, voltage table and freq_cmb, filled dynamicly */
554 int *vm_millivolts; /*size VL_MAX */
555 unsigned int (*freqs_cmb)[VL_MAX]; /* size VM_RAIL_MAX */
556};
557
558#define debug_wt_reg(val, reg) \
559do { \
560 /*printf(" %08x ==> [%x]\n", val, reg);*/ \
561 __raw_writel(val, reg); \
562} while (0)
563
564/* current platform OP struct */
565static struct platform_opt *cur_platform_opt;
566
567static LIST_HEAD(core_op_list);
568
569/* current core OP */
570static struct cpu_opt *cur_cpu_op;
571
572/* current DDR/AXI OP */
573static struct ddr_opt *cur_ddr_op;
574static struct axi_opt *cur_axi_op;
575
576static unsigned int cpu_sel2_srcrate(enum ap_clk_sel ap_sel);
577static unsigned int ddr_sel2_srcrate(enum ddr_clk_sel ddr_sel);
578static unsigned int axi_sel2_srcrate(enum axi_clk_sel axi_sel);
579
580static unsigned int cal_comp_volts_req(enum vcore_comps comp,
581 unsigned int rate);
582
583static int set_volt(u32 vol);
584static u32 get_volt(void);
585
586static int hwdfc_enable; /* enable HW-DFC */
587
588/* fuse related */
589static unsigned int uidro;
590static unsigned int uiprofile;
591static unsigned int uichipversion;
592
593/*
594 * used to record dummy boot up PP, define it here
595 * as the default src and div value read from register
596 * is NOT the real core and ddr,axi rate.
597 * This default boot OP is from PP table.
598 */
599static struct cpu_opt helan2_cpu_bootop = {
600 .pclk = 312,
601 .pdclk = 156,
602 .baclk = 78,
603 .ap_clk_src = 624,
604};
605
606static struct ddr_opt helan2_ddr_bootop = {
607 .dclk = 156,
608 .ddr_clk_src = 624,
609};
610
611static struct axi_opt helan2_axi_bootop = {
612 .aclk = 104,
613 .axi_clk_src = 416,
614};
615
616/*
617 * For HELAN2:
618 * PCLK = AP_CLK_SRC / (CORE_CLK_DIV + 1)
619 * BIU_CLK = PCLK / (BIU_CLK_DIV + 1)
620 * MC_CLK = PCLK / (MC_CLK_DIV + 1)
621 */
622static struct cpu_opt helan2_op_array[] = {
623 {
624 .pclk = 312,
625 .pdclk = 156,
626 .baclk = 156,
627 .ap_clk_sel = AP_CLK_SRC_PLL1_624,
628 },
629 {
630 .pclk = 624,
631 .pdclk = 312,
632 .baclk = 156,
633 .ap_clk_sel = AP_CLK_SRC_PLL1_624,
634 },
635 {
636 .pclk = 832,
637 .pdclk = 416,
638 .baclk = 208,
639 .ap_clk_sel = AP_CLK_SRC_PLL1_832,
640 },
641 {
642 .pclk = 1057,
643 .pdclk = 528,
644 .baclk = 264,
645 .ap_clk_sel = AP_CLK_SRC_PLL2,
646 },
647 {
648 .pclk = 1248,
649 .pdclk = 624,
650 .baclk = 312,
651 .ap_clk_sel = AP_CLK_SRC_PLL1_1248,
652 },
653 {
654 .pclk = 1526,
655 .pdclk = 763,
656 .baclk = 381,
657 .ap_clk_sel = AP_CLK_SRC_PLL3P,
658 },
659};
660
661/*
662 * 1) Please don't select ddr from pll1 but axi from pll2
663 * 2) FIXME: high ddr request means high axi is NOT
664 * very reasonable
665 */
666static struct ddr_opt lpddr800_ddr_oparray[] = {
667 {
668 .dclk = 156,
669 .ddr_tbl_index = 2,
670 .ddr_clk_sel = DDR_CLK_SRC_PLL1_624,
671 },
672 {
673 .dclk = 312,
674 .ddr_tbl_index = 4,
675 .ddr_clk_sel = DDR_CLK_SRC_PLL1_624,
676 },
677 {
678 .dclk = 416,
679 .ddr_tbl_index = 6,
680 .ddr_clk_sel = DDR_CLK_SRC_PLL1_832,
681 },
682 {
683 .dclk = 528,
684 .ddr_tbl_index = 8,
685 .ddr_clk_sel = DDR_CLK_SRC_PLL2,
686 },
687 {
688 .dclk = 797,
689 .ddr_tbl_index = 10,
690 .ddr_clk_sel = DDR_CLK_SRC_PLL4,
691 },
692};
693
694static struct ddr_opt lpddr667_ddr_oparray[] = {
695 {
696 .dclk = 156,
697 .ddr_tbl_index = 2,
698 .ddr_freq_level = 0,
699 .ddr_clk_sel = DDR_CLK_SRC_PLL1_624,
700 },
701 {
702 .dclk = 312,
703 .ddr_tbl_index = 4,
704 .ddr_freq_level = 1,
705 .ddr_clk_sel = DDR_CLK_SRC_PLL1_624,
706 },
707 {
708 .dclk = 416,
709 .ddr_tbl_index = 6,
710 .ddr_freq_level = 2,
711 .ddr_clk_sel = DDR_CLK_SRC_PLL1_832,
712 },
713 {
714 .dclk = 528,
715 .ddr_tbl_index = 8,
716 .ddr_freq_level = 3,
717 .ddr_clk_sel = DDR_CLK_SRC_PLL2,
718 },
719 {
720 .dclk = 667,
721 .ddr_tbl_index = 10,
722 .ddr_freq_level = 4,
723 .ddr_clk_sel = DDR_CLK_SRC_PLL4,
724 },
725};
726
727static struct ddr_opt lpddr533_ddr_oparray[] = {
728 {
729 .dclk = 156,
730 .ddr_tbl_index = 2,
731 .ddr_freq_level = 0,
732 .ddr_clk_sel = DDR_CLK_SRC_PLL1_624,
733 },
734 {
735 .dclk = 312,
736 .ddr_tbl_index = 4,
737 .ddr_freq_level = 1,
738 .ddr_clk_sel = DDR_CLK_SRC_PLL1_624,
739 },
740 {
741 .dclk = 416,
742 .ddr_tbl_index = 6,
743 .ddr_freq_level = 2,
744 .ddr_clk_sel = DDR_CLK_SRC_PLL1_832,
745 },
746 {
747 .dclk = 528,
748 .ddr_tbl_index = 8,
749 .ddr_freq_level = 3,
750 .ddr_clk_sel = DDR_CLK_SRC_PLL2,
751 },
752};
753
754static struct ddr_opt lpddr400_ddr_oparray[] = {
755 {
756 .dclk = 156,
757 .ddr_tbl_index = 2,
758 .ddr_freq_level = 0,
759 .ddr_clk_sel = DDR_CLK_SRC_PLL1_624,
760 },
761 {
762 .dclk = 312,
763 .ddr_tbl_index = 4,
764 .ddr_freq_level = 1,
765 .ddr_clk_sel = DDR_CLK_SRC_PLL1_624,
766 },
767 {
768 .dclk = 398,
769 .ddr_tbl_index = 6,
770 .ddr_freq_level = 2,
771 .ddr_clk_sel = DDR_CLK_SRC_PLL2,
772 },
773};
774
775static struct axi_opt axi_oparray[] = {
776 {
777 .aclk = 156,
778 .axi_clk_sel = AXI_CLK_SRC_PLL1_624,
779 },
780 {
781 .aclk = 208,
782 .axi_clk_sel = AXI_CLK_SRC_PLL1_416,
783 },
784 {
785 .aclk = 312,
786 .axi_clk_sel = AXI_CLK_SRC_PLL1_624,
787 },
788};
789
790/*
791 * core and ddr opt combination vary from platform to platform
792 * LPDDR400 pll2vco 1600M, pll2 800M, pll2p 400M
793 * pll3vco 2358M, pll3 1179M, pll3p 1179M
794 * LPDDR533 pll2vco 2132M, pll2 1066M, pll2p 533M
795 * pll3vco 2358M, pll3 1179M, pll3p 1179M
796 * LPDDR667 pll2vco 2132M, pll2 1066M, pll2p 533M
797 * pll3vco 2358M, pll3 1179M, pll3p 1179M
798 * pll4vco 2668M, pll4 1334M, pll4p 667M
799 * LPDDR800 pll2vco 2132M, pll2 1066M, pll2p 533M
800 * pll3vco 2358M, pll3 1179M, pll3p 1179M
801 * pll4vco 1600M, pll4 1600M, pll4p 800M
802 */
803static struct platform_opt platform_op_arrays[] = {
804 {
805#if 0
806 .cpuid = 0x8000,
807 .chipid = 0xf01188,
808#endif
809 .cpu_name = "HELAN2",
810 .cpu_opt = helan2_op_array,
811 .cpu_opt_size = ARRAY_SIZE(helan2_op_array),
812 .ddrtype = DDR_400M,
813 .ddr_opt = lpddr400_ddr_oparray,
814 .ddr_opt_size = ARRAY_SIZE(lpddr400_ddr_oparray),
815 .axi_opt = axi_oparray,
816 .axi_opt_size = ARRAY_SIZE(axi_oparray),
817 .pll2vcofreq = 1595,
818 .pll2freq = 797,
819 .pll2pfreq = 797,
820 .pll3vcofreq = 1526,
821 .pll3freq = 1526,
822 .pll3pfreq = 1526,
823 .df_max_cpurate = 2000,
824 },
825 {
826#if 0
827 .cpuid = 0x8000,
828 .chipid = 0xf01188,
829#endif
830 .cpu_name = "HELAN2",
831 .cpu_opt = helan2_op_array,
832 .cpu_opt_size = ARRAY_SIZE(helan2_op_array),
833 .ddrtype = DDR_533M,
834 .ddr_opt = lpddr533_ddr_oparray,
835 .ddr_opt_size = ARRAY_SIZE(lpddr533_ddr_oparray),
836 .axi_opt = axi_oparray,
837 .axi_opt_size = ARRAY_SIZE(axi_oparray),
838 .pll2vcofreq = 2115,
839 .pll2freq = 1057,
840 .pll2pfreq = 2115,
841 .pll3vcofreq = 1526,
842 .pll3freq = 1526,
843 .pll3pfreq = 1526,
844 .df_max_cpurate = 2000,
845 },
846 {
847#if 0
848 .cpuid = 0x8000,
849 .chipid = 0xf01188,
850#endif
851 .cpu_name = "HELAN2",
852 .cpu_opt = helan2_op_array,
853 .cpu_opt_size = ARRAY_SIZE(helan2_op_array),
854 .ddrtype = DDR_667M,
855 .ddr_opt = lpddr667_ddr_oparray,
856 .ddr_opt_size = ARRAY_SIZE(lpddr667_ddr_oparray),
857 .axi_opt = axi_oparray,
858 .axi_opt_size = ARRAY_SIZE(axi_oparray),
859 .pll2vcofreq = 2115,
860 .pll2freq = 1057,
861 .pll2pfreq = 2115,
862 .pll3vcofreq = 1526,
863 .pll3freq = 1526,
864 .pll3pfreq = 1526,
865 .pll4vcofreq = 2669,
866 .pll4freq = 1334,
867 .pll4pfreq = 667,
868 .df_max_cpurate = 2000,
869 },
870 {
871#if 0
872 .cpuid = 0x8000,
873 .chipid = 0xf01188,
874#endif
875 .cpu_name = "HELAN2",
876 .cpu_opt = helan2_op_array,
877 .cpu_opt_size = ARRAY_SIZE(helan2_op_array),
878 .ddrtype = DDR_800M,
879 .ddr_opt = lpddr800_ddr_oparray,
880 .ddr_opt_size = ARRAY_SIZE(lpddr800_ddr_oparray),
881 .axi_opt = axi_oparray,
882 .axi_opt_size = ARRAY_SIZE(axi_oparray),
883 .pll2vcofreq = 2115,
884 .pll2freq = 1057,
885 .pll2pfreq = 2115,
886 .pll3vcofreq = 1526,
887 .pll3freq = 1526,
888 .pll3pfreq = 1526,
889 .pll4vcofreq = 1595,
890 .pll4freq = 1595,
891 .pll4pfreq = 797,
892 .df_max_cpurate = 2000,
893 },
894};
895
896/* FIXME: For bring up only */
897static int vm_mv_helan2_svc[][VL_MAX] = {
898 {1100, 1200, 1300, 1325},
899};
900
901/* FIXME: For bring up only */
902static unsigned int freqs_cmb_helan2[VM_RAIL_MAX][VL_MAX] = {
903 { 312, 624, 1248, 1500 }, /* CORE */
904 { 156, 398, 528, 800 }, /* DDR */
905 { 208, 312, 312, 312 }, /* AXI */
906};
907
908/* read chip profile from FUSE */
909static int get_profile(void)
910{
911 return uiprofile;
912}
913
914/* read chip version from FUSE */
915static int __attribute__ ((unused)) get_cpu_version(void)
916{
917 /* FIXME: update according to fuse definition */
918 return uichipversion;
919}
920
921#if 0
922static unsigned int convert_fuses2profile(unsigned int uiFuses)
923{
924 unsigned int uiProfile = 0;
925 unsigned int uiTemp = 3, uiTemp2 = 1;
926 unsigned int i;
927
928 for (i = 0; i < PROFILE_NUM; i++) {
929 uiTemp |= uiTemp2 << (i + 1);
930 if (uiTemp == uiFuses)
931 uiProfile = i + 1;
932 }
933
934 return uiProfile;
935}
936#endif
937
938/* FIXME: must remove the table after has fuse info !!! */
939struct svtrng {
940 unsigned int min;
941 unsigned int max;
942 unsigned int profile;
943};
944
945static struct svtrng svtrngtb_z0[] = {
946 {0, 295, 15},
947 {296, 308, 14},
948 {309, 320, 13},
949 {321, 332, 12},
950 {333, 344, 11},
951 {345, 357, 10},
952 {358, 370, 9},
953 {371, 382, 8},
954 {383, 394, 7},
955 {395, 407, 6},
956 {408, 420, 5},
957 {421, 432, 4},
958 {433, 444, 3},
959 {445, 0xffffffff, 2},
960 /* NOTE: rsved profile 1, by default use profile 0 */
961};
962
963static unsigned int convert_svtdro2profile(unsigned int uisvtdro)
964{
965 unsigned int uiProfile = 0, idx;
966
967 for (idx = 0; idx < ARRAY_SIZE(svtrngtb_z0); idx++) {
968 if (uisvtdro >= svtrngtb_z0[idx].min &&
969 uisvtdro <= svtrngtb_z0[idx].max) {
970 uiProfile = svtrngtb_z0[idx].profile;
971 break;
972 }
973 }
974
975 return uiProfile;
976}
977
978static void __init_read_ultinfo(void)
979{
980 unsigned int uimanupara_31_00 = 0;
981 unsigned int uimanupara_63_32 = 0;
982 unsigned int uimanupara_95_64 = 0;
983 unsigned int uiblk4para_95_64 = 0;
984 unsigned int uiallocrev = 0;
985 unsigned int uifab = 0;
986 unsigned int uirun = 0;
987 unsigned int uiwafer = 0;
988 unsigned int uix = 0;
989 unsigned int uiy = 0;
990 unsigned int uiparity = 0;
991 unsigned int uigeustatus = 0;
992 unsigned int uifuses = 0;
993 unsigned int uisvtdro = 0;
994 u64 uluid = 0;
995
996 /*
997 * Read out DRO value, need enable GEU clock, if already disable,
998 * need enable it firstly
999 */
1000#ifndef CONFIG_TZ_HYPERVISOR
1001 uigeustatus = __raw_readl(APMU_GEU);
1002 if (!(uigeustatus & 0x30)) {
1003 __raw_writel((uigeustatus | 0x30), APMU_GEU);
1004 udelay(10);
1005 }
1006 uimanupara_31_00 = __raw_readl(MANU_PARA_31_00);
1007 uimanupara_63_32 = __raw_readl(MANU_PARA_63_32);
1008 uimanupara_95_64 = __raw_readl(MANU_PARA_95_64);
1009 uiblk4para_95_64 = __raw_readl(BLOCK4_PARA_31_00);
1010 uifuses = __raw_readl(BLOCK0_224_255);
1011 uluid = __raw_readl(UID_H_32);
1012 uluid = (uluid << 32) | __raw_readl(UID_L_32);
1013 __raw_writel(uigeustatus, APMU_GEU);
1014#else
1015 /* FIXME: add TZ_HYPERVISOR support here */
1016#endif
1017
1018 printf(" 0x%x 0x%x 0x%x 0x%x\n",
1019 uimanupara_31_00, uimanupara_63_32,
1020 uimanupara_95_64, uiblk4para_95_64);
1021
1022 uiallocrev = uimanupara_31_00 & 0x7;
1023 uifab = (uimanupara_31_00 >> 3) & 0x1f;
1024 uirun = ((uimanupara_63_32 & 0x3) << 24)
1025 | ((uimanupara_31_00 >> 8) & 0xffffff);
1026 uiwafer = (uimanupara_63_32 >> 2) & 0x1f;
1027 uix = (uimanupara_63_32 >> 7) & 0xff;
1028 uiy = (uimanupara_63_32 >> 15) & 0xff;
1029 uiparity = (uimanupara_63_32 >> 23) & 0x1;
1030 uidro = (uimanupara_95_64 >> 4) & 0x3ff;
1031 uisvtdro = uiblk4para_95_64 & 0x3ff;
1032
1033 /* bit 240 ~ 255 for Profile information */
1034 uifuses = (uifuses >> 16) & 0x0000FFFF;
1035#if 0
1036 uiprofile = convert_fuses2profile(uifuses);
1037#endif
1038 uiprofile = convert_svtdro2profile(uisvtdro);
1039
1040 printf(" ");
1041 printf(" *********************************\n");
1042 printf(" * ULT: %08X%08X *\n",
1043 uimanupara_63_32, uimanupara_31_00);
1044 printf(" *********************************\n");
1045 printf(" ULT decoded below\n");
1046 printf(" alloc_rev[2:0] = %d\n", uiallocrev);
1047 printf(" fab [ 7: 3] = %d\n", uifab);
1048 printf(" run [33: 8] = %d (0x%X)\n", uirun, uirun);
1049 printf(" wafer [38:34] = %d\n", uiwafer);
1050 printf(" x [46:39] = %d\n", uix);
1051 printf(" y [54:47] = %d\n", uiy);
1052 printf(" parity [55:55] = %d\n", uiparity);
1053 printf(" *********************************\n");
1054 printf(" *********************************\n");
1055 printf(" LVTDRO [77:68] = %d\n", uidro);
1056 printf(" SVTDRO [9:0] = %d\n", uisvtdro);
1057 printf(" Profile = %d\n", uiprofile);
1058 printf(" UID = %llx\n", uluid);
1059 printf(" *********************************\n");
1060 printf("\n");
1061}
1062
1063/* PLL post divider table */
1064static struct pll_post_div pll_post_div_tbl[] = {
1065 /* divider, reg vaule */
1066 {1, 0x0},
1067 {2, 0x1},
1068 {4, 0x2},
1069 {8, 0x3},
1070 {16, 0x4},
1071 {32, 0x5},
1072 {64, 0x6},
1073 {128, 0x7},
1074};
1075
1076static unsigned int __clk_pll_vco2intpi(unsigned long vco)
1077{
1078 unsigned int intpi;
1079
1080 if (vco >= 2500 && vco <= 3000)
1081 intpi = 8;
1082 else if (vco >= 2000)
1083 intpi = 6;
1084 else if (vco >= 1500)
1085 intpi = 5;
1086 else
1087 BUG_ON("Unsupported vco frequency for INTPI!\n");
1088
1089 return intpi;
1090}
1091
1092/*
1093 * Real amplitude percentage = amplitude / base
1094*/
1095static void __attribute__ ((unused)) __clk_pll_get_divrng(
1096 enum ssc_mode mode, unsigned long rate,
1097 unsigned int amplitude, unsigned int base,
1098 unsigned long vco, unsigned int *div,
1099 unsigned int *rng)
1100{
1101 unsigned int vco_avg;
1102 if (amplitude > (50 * base / 1000))
1103 BUG_ON("Amplitude can't exceed 5\%\n");
1104 switch (mode) {
1105 case CENTER_SPREAD:
1106 vco_avg = vco;
1107 *div = (vco_avg / rate) >> 4;
1108 break;
1109 case DOWN_SPREAD:
1110 vco_avg = vco * (base - amplitude / 2) / base;
1111 *div = (vco_avg / rate) >> 3;
1112 break;
1113 default:
1114 printf("Unsupported SSC MODE!\n");
1115 return;
1116 }
1117 if (*div == 0)
1118 *div = 1;
1119 /* SSC_RNGE = Desired_SSC_Amplitude / (SSC_FREQ_DIV * 2^-28) */
1120 *rng = (1 << 28) / (*div * base / amplitude);
1121}
1122
1123/* convert post div reg setting to divider val */
1124static unsigned int __pll_divsel2div(unsigned int divselval)
1125{
1126 unsigned int i;
1127
1128 for (i = 0; i < ARRAY_SIZE(pll_post_div_tbl); i++) {
1129 if (divselval == pll_post_div_tbl[i].divselval)
1130 return pll_post_div_tbl[i].div;
1131 }
1132 BUG_ON(i == ARRAY_SIZE(pll_post_div_tbl));
1133 return 0;
1134}
1135
1136/* PLL range 1.2G~3G */
1137static void __clk_pll_rate2rng(unsigned long rate, unsigned int *kvco)
1138{
1139 if (rate >= 2600 && rate <= 3000)
1140 *kvco = 0xf;
1141 else if (rate >= 2400)
1142 *kvco = 0xe;
1143 else if (rate >= 2200)
1144 *kvco = 0xd;
1145 else if (rate >= 2000)
1146 *kvco = 0xc;
1147 else if (rate >= 1750)
1148 *kvco = 0xb;
1149 else if (rate >= 1500)
1150 *kvco = 0xa;
1151 else if (rate >= 1350)
1152 *kvco = 0x9;
1153 else if (rate >= 1200)
1154 *kvco = 0x8;
1155 else
1156 printf("%s rate %lu out of range!\n",
1157 __func__, rate);
1158}
1159
1160/* rate unit Mhz */
1161static unsigned int __clk_pll_calc_div(unsigned long rate,
1162 unsigned long parent_rate, unsigned int *div)
1163{
1164 unsigned int i;
1165 *div = 0;
1166
1167 for (i = 0; i < ARRAY_SIZE(pll_post_div_tbl); i++) {
1168 if (rate == (parent_rate / pll_post_div_tbl[i].div)) {
1169 *div = pll_post_div_tbl[i].div;
1170 return pll_post_div_tbl[i].divselval;
1171 }
1172 }
1173 BUG_ON(i == ARRAY_SIZE(pll_post_div_tbl));
1174 return 0;
1175}
1176
1177static u32 pll2_is_enabled(void)
1178{
1179 union pmum_pll2cr pll2cr;
1180 pll2cr.v = __raw_readl(MPMU_PLL2CR);
1181
1182 /* ctrl = 0(hw enable) or ctrl = 1&&en = 1(sw enable) */
1183 /* ctrl = 1&&en = 0(sw disable) */
1184 if (pll2cr.b.ctrl && (!pll2cr.b.en))
1185 return 0;
1186 else
1187 return 1;
1188}
1189
1190/*
1191 * Pll2 has three frequency output, pll2 pll2p and pll2_div3
1192 * pll2 pll2p and pll2_div3 are divided from pll2 vco
1193 */
1194static void set_pll2_freq(u32 pll2vco_freq, u32 pll2_freq, u32 pll2p_freq)
1195{
1196 union pmum_pll2cr pll2cr;
1197 union apb_spare_pllswcr pll2_sw_ctrl;
1198 union pmum_posr pll2posr;
1199 u32 kvco;
1200 u32 divselse, divseldiff, pll2_div, pll2p_div;
1201 unsigned int delaytime = 14;
1202
1203 /* do nothing if pll2 is enabled */
1204 if (pll2_is_enabled()) {
1205 printf("Disable Pll2 before change its rate\n");
1206 return;
1207 }
1208
1209 /* calc vco rate range */
1210 __clk_pll_rate2rng(pll2vco_freq, &kvco);
1211
1212 /* calc pll2 and pll2p divider */
1213 divselse = __clk_pll_calc_div(pll2_freq, pll2vco_freq, &pll2_div);
1214 divseldiff = __clk_pll_calc_div(pll2p_freq, pll2vco_freq, &pll2p_div);
1215
1216 /* pll2 SW ctrl setting */
1217 pll2_sw_ctrl.v = __raw_readl(APB_SPARE_PLL2CR);
1218 pll2_sw_ctrl.b.avvd1815_sel = 1;
1219 pll2_sw_ctrl.b.vddm = 1;
1220 pll2_sw_ctrl.b.vddl = 4;
1221 pll2_sw_ctrl.b.icp = 3;
1222 pll2_sw_ctrl.b.pll_bw_sel = 0;
1223 pll2_sw_ctrl.b.kvco = kvco;
1224 pll2_sw_ctrl.b.ctune = 1;
1225 pll2_sw_ctrl.b.divseldiff = divseldiff;
1226 pll2_sw_ctrl.b.divselse = divselse;
1227 pll2_sw_ctrl.b.diffclken = 1;
1228 pll2_sw_ctrl.b.bypassen = 0;
1229 pll2_sw_ctrl.b.gatectl = 0;
1230 pll2_sw_ctrl.b.fd = 4;
1231 debug_wt_reg(pll2_sw_ctrl.v, APB_SPARE_PLL2CR);
1232
1233 /* (Refclk * 4 * Fbdiv) / Refdiv = pll2freq, Refclk = 26M */
1234 pll2cr.v = 0;
1235 pll2cr.b.pll2refd = 3;
1236 pll2cr.b.pll2fbd = pll2vco_freq * pll2cr.b.pll2refd / (26 * 4);
1237 /* we must lock refd/fbd first before enabling PLL2 */
1238 pll2cr.b.ctrl = 1;
1239 debug_wt_reg(pll2cr.v, MPMU_PLL2CR);
1240 pll2cr.b.ctrl = 0; /* Let HW control PLL2 */
1241 debug_wt_reg(pll2cr.v, MPMU_PLL2CR);
1242
1243 udelay(30);
1244 while ((!(__raw_readl(MPMU_POSR) & POSR_PLL2_LOCK)) && delaytime) {
1245 udelay(5);
1246 delaytime--;
1247 }
1248 if (unlikely(!delaytime))
1249 BUG_ON("PLL2 is NOT locked after 100us enable!\n");
1250 pll2posr.v = __raw_readl(MPMU_POSR);
1251 printf("PLL2_VCO enable@%dMhz, PLL2@%dMhz, PLL2P@%dMhz, PLL2_DIV3@%dMhz\n"
1252 "SWCR[w%x,r%x] PLL2CR[w%x,r%x] "
1253 "PLL2 shadow refd%d, fbd%d\n",
1254 pll2vco_freq, pll2vco_freq / pll2_div,
1255 pll2vco_freq / pll2p_div, pll2vco_freq / 3,
1256 pll2_sw_ctrl.v, __raw_readl(APB_SPARE_PLL2CR),
1257 pll2cr.v, __raw_readl(MPMU_PLL2CR),
1258 pll2posr.b.pll2refd, pll2posr.b.pll2fbd);
1259
1260 return;
1261}
1262
1263/* frequency unit Mhz, return pll2 vco freq */
1264static u32 get_pll2_freq(u32 *pll2_freq, u32 *pll2p_freq)
1265{
1266 union pmum_pll2cr pll2cr;
1267 union apb_spare_pllswcr pll2_sw_ctl;
1268 u32 pll2_vco, pll2_div, pll2p_div, pll2refd;
1269
1270 /* return 0 if pll2 is disabled(ctrl = 1, en = 0) */
1271 if (!pll2_is_enabled()) {
1272 printf("%s PLL2 is not enabled!\n", __func__);
1273 *pll2_freq = 0;
1274 *pll2p_freq = 0;
1275 return 0;
1276 }
1277
1278 pll2cr.v = __raw_readl(MPMU_PLL2CR);
1279 pll2refd = pll2cr.b.pll2refd;
1280 BUG_ON(pll2refd > 3);
1281
1282 pll2_vco = 26 * 4 * pll2cr.b.pll2fbd / pll2refd;
1283
1284 pll2_sw_ctl.v = __raw_readl(APB_SPARE_PLL2CR);
1285 pll2_div = __pll_divsel2div(pll2_sw_ctl.b.divselse);
1286 pll2p_div = __pll_divsel2div(pll2_sw_ctl.b.divseldiff);
1287 *pll2_freq = pll2_vco / pll2_div;
1288 *pll2p_freq = pll2_vco / pll2p_div;
1289
1290 return pll2_vco;
1291}
1292
1293/*
1294 * 1. Whenever PLL2 is enabled, ensure it's set as HW activation.
1295 * 2. When PLL2 is disabled (no one uses PLL2 as source),
1296 * set it as SW activation.
1297 */
1298static int pll2_refcnt;
1299void turn_off_pll2(void)
1300{
1301 union pmum_pll2cr pll2cr;
1302
1303 pll2_refcnt--;
1304 if (pll2_refcnt < 0)
1305 printf("unmatched pll2_refcnt\n");
1306 if (pll2_refcnt == 0) {
1307 pll2cr.v = __raw_readl(MPMU_PLL2CR);
1308 pll2cr.b.ctrl = 1; /* Let SW control PLL2 */
1309 pll2cr.b.en = 0; /* disable PLL2 by en bit */
1310 __raw_writel(pll2cr.v, MPMU_PLL2CR);
1311 printf("Disable pll2 as it is not used!\n");
1312 }
1313}
1314
1315/* must be called after __init_platform_opt */
1316void turn_on_pll2(void)
1317{
1318 u32 pll2vco, pll2, pll2p;
1319
1320 BUG_ON(!cur_platform_opt ||
1321 !cur_platform_opt->pll2vcofreq);
1322
1323 pll2_refcnt++;
1324 if (pll2_refcnt == 1) {
1325 pll2vco = cur_platform_opt->pll2vcofreq;
1326 pll2 = cur_platform_opt->pll2freq;
1327 pll2p = cur_platform_opt->pll2pfreq;
1328 set_pll2_freq(pll2vco, pll2, pll2p);
1329 }
1330}
1331
1332static int pll_refcnt[PLL_MAX];
1333
1334static unsigned int pllx_cr_reg[PLL_MAX] = {
1335 0, 0, 0, MPMU_PLL3CR, MPMU_PLL4CR,
1336};
1337
1338static unsigned int pllx_sw_reg[PLL_MAX] = {
1339 0, 0, 0, APB_SPARE_PLL3CR, APB_SPARE_PLL4CR,
1340};
1341
1342static unsigned int pllx_ssc_ctrl_reg[PLL_MAX] = {
1343 0, 0, APB_PLL2_SSC_CTRL, APB_PLL3_SSC_CTRL, APB_PLL4_SSC_CTRL,
1344};
1345
1346static unsigned int pllx_ssc_conf_reg[PLL_MAX] = {
1347 0, 0, APB_PLL2_SSC_CONF, APB_PLL3_SSC_CONF, APB_PLL4_SSC_CONF,
1348};
1349
1350static void __attribute__ ((unused)) enable_pllx_ssc(
1351 enum ssc_mode mode, unsigned int div,
1352 unsigned int rng, enum pll pll,
1353 unsigned long vcofreq)
1354{
1355 union apb_pllx_ssc_ctrl pllx_ssc_ctrl;
1356 union apb_pllx_ssc_conf pllx_ssc_conf;
1357
1358 u32 pll_ssc_ctl_reg = pllx_ssc_ctrl_reg[pll];
1359 u32 pll_ssc_cnf_reg = pllx_ssc_conf_reg[pll];
1360
1361 unsigned int intpi = __clk_pll_vco2intpi(vcofreq);
1362
1363 pllx_ssc_conf.v = __raw_readl(pll_ssc_cnf_reg);
1364 pllx_ssc_conf.b.ssc_freq_div = div;
1365 pllx_ssc_conf.b.ssc_rnge = rng;
1366 __raw_writel(pllx_ssc_conf.v, pll_ssc_cnf_reg);
1367
1368 pllx_ssc_ctrl.v = __raw_readl(pll_ssc_ctl_reg);
1369 pllx_ssc_ctrl.b.pi_en = 1;
1370 pllx_ssc_ctrl.b.reset_pi = 0;
1371 pllx_ssc_ctrl.b.pi_loop_mode = 0;
1372 pllx_ssc_ctrl.b.clk_det_en = 1;
1373 pllx_ssc_ctrl.b.intpi = intpi;
1374 pllx_ssc_ctrl.b.intpr = 4;
1375 __raw_writel(pllx_ssc_ctrl.v, pll_ssc_ctl_reg);
1376
1377 pllx_ssc_ctrl.b.ssc_mode = mode;
1378 pllx_ssc_ctrl.b.reset_ssc = 1;
1379 pllx_ssc_ctrl.b.ssc_clk_en = 1;
1380 __raw_writel(pllx_ssc_ctrl.v, pll_ssc_ctl_reg);
1381
1382 udelay(1);
1383 pllx_ssc_ctrl.b.reset_ssc = 0;
1384 __raw_writel(pllx_ssc_ctrl.v, pll_ssc_ctl_reg);
1385 udelay(1);
1386 pllx_ssc_ctrl.b.pi_loop_mode = 1;
1387 __raw_writel(pllx_ssc_ctrl.v, pll_ssc_ctl_reg);
1388
1389 printf("enable ssc for pll%d ssc_conf[addr: 0x%x] [sw:%x] [hw:%x]\n"
1390 "ssc_ctrl[addr 0x%x] [sw:%x] [hw:%x]\n",
1391 pll,
1392 pll_ssc_cnf_reg, pllx_ssc_conf.v, __raw_readl(pll_ssc_cnf_reg),
1393 pll_ssc_ctl_reg, pllx_ssc_ctrl.v, __raw_readl(pll_ssc_ctl_reg));
1394}
1395
1396static void __attribute__ ((unused)) disable_pllx_ssc(enum pll pll)
1397{
1398 union apb_pllx_ssc_ctrl pllx_ssc_ctrl;
1399 u32 pll_ssc_ctl_reg = pllx_ssc_ctrl_reg[pll];
1400
1401 pllx_ssc_ctrl.v = __raw_readl(pll_ssc_ctl_reg);
1402 pllx_ssc_ctrl.b.pi_en = 0;
1403 pllx_ssc_ctrl.b.ssc_clk_en = 0;
1404 pllx_ssc_ctrl.b.clk_det_en = 0;
1405 pllx_ssc_ctrl.b.pi_loop_mode = 0;
1406 __raw_writel(pllx_ssc_ctrl.v, pll_ssc_ctl_reg);
1407
1408 printf("disable ssc for pll%d ssc_ctrl[addr 0x%x] [sw:%x] [hw:%x]\n",
1409 pll, pll_ssc_ctl_reg,
1410 pllx_ssc_ctrl.v, __raw_readl(pll_ssc_ctl_reg));
1411}
1412
1413static u32 pll_is_enabled(enum pll pll)
1414{
1415 union pmum_pllxcr pllxcr;
1416 u32 pll_cr_reg = pllx_cr_reg[pll];
1417 pllxcr.v = __raw_readl(pll_cr_reg);
1418 /*
1419 * PLLXCR[19] = 0x0 means PLLX is disabled
1420 */
1421 if (!pllxcr.b.pll_pu)
1422 return 0;
1423 else
1424 return 1;
1425}
1426
1427static void set_pll_freq(enum pll pll, u32 pllvco_freq,
1428 u32 pll_freq, u32 pllp_freq)
1429{
1430 union pmum_pllxcr pllcr;
1431 union apb_spare_pllswcr pll_sw_ctrl;
1432 u32 kvco;
1433 u32 divselse, divseldiff, pll_div, pllp_div;
1434 unsigned int delaytime = 14;
1435 u32 pll_cr_reg, pll_sw_reg;
1436
1437 if (pll == PLL2) {
1438 set_pll2_freq(pllvco_freq, pll_freq, pllp_freq);
1439 return;
1440 }
1441
1442 /* do nothing if pll is enabled */
1443 if (pll_is_enabled(pll)) {
1444 printf("Pll%d is already enabled!\n", pll);
1445 return;
1446 }
1447
1448 pll_cr_reg = pllx_cr_reg[pll];
1449 pll_sw_reg = pllx_sw_reg[pll];
1450 /* calc vco rate range */
1451 __clk_pll_rate2rng(pllvco_freq, &kvco);
1452
1453 /* calc pll and pllp divider */
1454 divselse = __clk_pll_calc_div(pll_freq, pllvco_freq, &pll_div);
1455 divseldiff = __clk_pll_calc_div(pllp_freq, pllvco_freq, &pllp_div);
1456
1457 /* pll SW ctrl setting */
1458 pll_sw_ctrl.v = __raw_readl(pll_sw_reg);
1459 pll_sw_ctrl.b.avvd1815_sel = 1;
1460 pll_sw_ctrl.b.vddm = 1;
1461 pll_sw_ctrl.b.vddl = 4;
1462 pll_sw_ctrl.b.icp = 3;
1463 pll_sw_ctrl.b.pll_bw_sel = 0;
1464 pll_sw_ctrl.b.kvco = kvco;
1465 pll_sw_ctrl.b.ctune = 1;
1466 pll_sw_ctrl.b.divseldiff = divseldiff;
1467 pll_sw_ctrl.b.divselse = divselse;
1468 pll_sw_ctrl.b.diffclken = 1;
1469 pll_sw_ctrl.b.bypassen = 0;
1470 pll_sw_ctrl.b.gatectl = 0;
1471 pll_sw_ctrl.b.fd = 4;
1472 __raw_writel(pll_sw_ctrl.v, pll_sw_reg);
1473
1474 /* (Refclk * 4 * Fbdiv) / Refdiv = pllxfreq, Refclk = 26M */
1475 pllcr.v = __raw_readl(pll_cr_reg);
1476 pllcr.b.pllrefd = 3;
1477 pllcr.b.pllfbd = pllvco_freq * pllcr.b.pllrefd / (26 * 4);
1478 pllcr.b.pll_pu = 1;
1479 __raw_writel(pllcr.v, pll_cr_reg);
1480
1481 udelay(30);
1482 while ((!((__raw_readl(MPMU_POSR) >> 27) & (1 << pll))) && delaytime) {
1483 udelay(5);
1484 delaytime--;
1485 }
1486
1487 if (unlikely(!delaytime))
1488 printf("PLL%d is NOT locked after 100us enable!\n", pll);
1489 printf("PLL%d_VCO enable@%dMhz, PLL%d@%dMhz, PLL%dP@%dMhz, PLL%d_DIV3@%dMhz\n"
1490 "SWCR[w%x,r%x] PLL%dCR[w%x,r%x]"
1491 "PLL%d refd%d, fbd%d\n",
1492 pll, pllvco_freq, pll, pllvco_freq / pll_div,
1493 pll, pllvco_freq / pllp_div, pll, pllvco_freq / 3,
1494 pll_sw_ctrl.v, __raw_readl(pll_sw_reg),
1495 pll, pllcr.v, __raw_readl(pll_cr_reg),
1496 pll, pllcr.b.pllrefd, pllcr.b.pllfbd);
1497
1498 return;
1499}
1500
1501/* frequency unit Mhz, return pll vco freq */
1502static u32 __attribute__ ((unused)) get_pll_freq(enum pll pll,
1503 u32 *pll_freq, u32 *pllp_freq)
1504{
1505 union pmum_pllxcr pllcr;
1506 union apb_spare_pllswcr pll_sw_ctl;
1507 u32 pll_vco, pll_div, pllp_div, pllrefd;
1508 u32 pll_cr_reg, pll_sw_reg;
1509
1510 if (pll == PLL2)
1511 return get_pll2_freq(pll_freq, pllp_freq);
1512
1513 /* return 0 if pll is disabled */
1514 if (!pll_is_enabled(pll)) {
1515 printf("%s PLL%d is not enabled!\n", __func__, pll);
1516 *pll_freq = 0;
1517 *pllp_freq = 0;
1518 return 0;
1519 }
1520
1521 pll_cr_reg = pllx_cr_reg[pll];
1522 pll_sw_reg = pllx_sw_reg[pll];
1523
1524 pllcr.v = __raw_readl(pll_cr_reg);
1525 pllrefd = pllcr.b.pllrefd;
1526 BUG_ON(pllrefd > 3);
1527
1528 pll_vco = 26 * 4 * pllcr.b.pllfbd / pllrefd;
1529
1530 pll_sw_ctl.v = __raw_readl(pll_sw_reg);
1531 pll_div = __pll_divsel2div(pll_sw_ctl.b.divselse);
1532 pllp_div = __pll_divsel2div(pll_sw_ctl.b.divseldiff);
1533 *pll_freq = pll_vco / pll_div;
1534 *pllp_freq = pll_vco / pllp_div;
1535
1536 return pll_vco;
1537}
1538
1539void turn_off_pll(enum pll pll)
1540{
1541 union pmum_pllxcr pllxcr;
1542 u32 pll_cr_reg;
1543 if (pll == PLL2) {
1544 turn_off_pll2();
1545 return;
1546 }
1547 pll_refcnt[pll]--;
1548 if (pll_refcnt[pll] < 0)
1549 printf("unmatched pll%d_refcnt\n", pll);
1550
1551 if (pll_refcnt[pll] == 0) {
1552 pll_cr_reg = pllx_cr_reg[pll];
1553 pllxcr.v = __raw_readl(pll_cr_reg);
1554 pllxcr.b.pll_pu = 0;
1555 __raw_writel(pllxcr.v, pll_cr_reg);
1556 printf("Disable pll%d as it is not used!\n", pll);
1557 }
1558}
1559
1560void turn_on_pll(enum pll pll)
1561{
1562 u32 pllvco_freq, pll_freq, pllp_freq;
1563
1564 if (pll == PLL2) {
1565 turn_on_pll2();
1566 return;
1567 }
1568 pll_refcnt[pll]++;
1569 if (pll_refcnt[pll] == 1) {
1570 switch (pll) {
1571 case PLL3:
1572 BUG_ON(!cur_platform_opt ||
1573 !cur_platform_opt->pll3vcofreq);
1574 pllvco_freq = cur_platform_opt->pll3vcofreq;
1575 pll_freq = cur_platform_opt->pll3freq;
1576 pllp_freq = cur_platform_opt->pll3pfreq;
1577 break;
1578 case PLL4:
1579 BUG_ON(!cur_platform_opt ||
1580 !cur_platform_opt->pll4vcofreq);
1581 pllvco_freq = cur_platform_opt->pll4vcofreq;
1582 pll_freq = cur_platform_opt->pll4freq;
1583 pllp_freq = cur_platform_opt->pll4pfreq;
1584 break;
1585 default:
1586 printf("Unsupported PLL%d operation\n", pll);
1587 return;
1588 }
1589 set_pll_freq(pll, pllvco_freq, pll_freq, pllp_freq);
1590 }
1591}
1592
1593static void __init_platform_opt(int ddr_mode)
1594{
1595 unsigned int i, chipid = 0;
1596 struct platform_opt *proc;
1597
1598 /*
1599 * ddr type is passed from OBM, FC code use this info
1600 * to identify DDR OPs.
1601 */
1602 if (ddr_mode >= DDR_TYPE_MAX)
1603 ddr_mode = DDR_400M;
1604
1605 for (i = 0; i < ARRAY_SIZE(platform_op_arrays); i++) {
1606 proc = platform_op_arrays + i;
1607 if ((proc->chipid == chipid) && (proc->ddrtype == ddr_mode))
1608 break;
1609 }
1610 BUG_ON(i == ARRAY_SIZE(platform_op_arrays));
1611 cur_platform_opt = proc;
1612}
1613
1614static struct cpu_rtcwtc cpu_rtcwtc_pxa1u88z1[] = {
1615 {.max_pclk = 624, .l1_rtc = 0x02222222, .l2_rtc = 0x00002221,},
1616 {.max_pclk = 1526, .l1_rtc = 0x02666666, .l2_rtc = 0x00006265,},
1617 {.max_pclk = 1803, .l1_rtc = 0x2AAAAAA, .l2_rtc = 0x0000A2A9,},
1618 {.max_pclk = 1976, .l1_rtc = 0x02EEEEEE, .l2_rtc = 0x0000E2ED,},
1619};
1620
1621static void __init_cpu_rtcwtc(struct cpu_opt *cpu_opt)
1622{
1623 struct cpu_rtcwtc *cpu_rtcwtc;
1624 unsigned int size, index;
1625
1626 cpu_rtcwtc = cpu_rtcwtc_pxa1u88z1;
1627 size = ARRAY_SIZE(cpu_rtcwtc_pxa1u88z1);
1628
1629 for (index = 0; index < size; index++)
1630 if (cpu_opt->pclk <= cpu_rtcwtc[index].max_pclk)
1631 break;
1632 if (index == size)
1633 index = size - 1;
1634
1635 cpu_opt->l1_rtc = cpu_rtcwtc[index].l1_rtc;
1636 cpu_opt->l2_rtc = cpu_rtcwtc[index].l2_rtc;
1637};
1638
1639/* Common condition here if you want to filter the core ops */
1640static unsigned int __is_cpu_op_invalid_com(struct cpu_opt *cop)
1641{
1642 unsigned int df_max_cpurate =
1643 cur_platform_opt->df_max_cpurate;
1644
1645 /* If pclk could not drive from src, invalid it */
1646 if (cop->ap_clk_src % cop->pclk)
1647 return 1;
1648
1649 /*
1650 * If pclk > default support max core frequency, invalid it
1651 */
1652 if (df_max_cpurate && (cop->pclk > df_max_cpurate))
1653 return 1;
1654
1655 return 0;
1656};
1657
1658/* plat extra condition here if you want to filter the core ops */
1659static unsigned int __is_cpu_op_invalid_plt(struct cpu_opt *cop)
1660{
1661 if (cur_platform_opt->is_cpuop_invalid_plt)
1662 return cur_platform_opt->is_cpuop_invalid_plt(cop);
1663
1664 /* no rule no filter */
1665 return 0;
1666}
1667
1668static void __init_cpu_opt(void)
1669{
1670 struct cpu_opt *cpu_opt, *cop;
1671 unsigned int cpu_opt_size = 0, i, idx = 0;
1672
1673 cpu_opt = cur_platform_opt->cpu_opt;
1674 cpu_opt_size = cur_platform_opt->cpu_opt_size;
1675
1676 debug("pclk(src:sel,div) l2clk(src,div)\t");
1677 debug("pdclk(src,div)\tbaclk(src,div)\t");
1678 debug("periphclk(src,div)\n");
1679
1680 for (i = 0; i < cpu_opt_size; i++) {
1681 cop = &cpu_opt[i];
1682 if (!cop->ap_clk_src)
1683 cop->ap_clk_src =
1684 cpu_sel2_srcrate(cop->ap_clk_sel);
1685 BUG_ON(cop->ap_clk_src < 0);
1686 /* check the invalid condition of this op */
1687 if (__is_cpu_op_invalid_com(cop))
1688 continue;
1689 if (__is_cpu_op_invalid_plt(cop))
1690 continue;
1691 /* add it into core op list */
1692 list_add_tail(&cop->node, &core_op_list);
1693 idx++;
1694
1695 /* fill the opt related setting */
1696 __init_cpu_rtcwtc(cop);
1697 cop->pclk_div =
1698 cop->ap_clk_src / cop->pclk - 1;
1699 if (cop->l2clk) {
1700 cop->l2clk_div =
1701 cop->pclk / cop->l2clk - 1;
1702 cop->pdclk_div =
1703 cop->l2clk / cop->pdclk - 1;
1704 cop->baclk_div =
1705 cop->l2clk / cop->baclk - 1;
1706 } else {
1707 cop->pdclk_div =
1708 cop->pclk / cop->pdclk - 1;
1709 cop->baclk_div =
1710 cop->pclk / cop->baclk - 1;
1711 }
1712 if (cop->periphclk)
1713 cop->periphclk_div =
1714 cop->pclk / (4 * cop->periphclk) - 1;
1715
1716 debug("%d(%d:%d,%d)\t%d([%s],%d)\t%d([%s],%d)\t%d([%s],%d)\t%d([%s],%d)\n",
1717 cop->pclk, cop->ap_clk_src,
1718 cop->ap_clk_sel & AP_SRC_SEL_MASK,
1719 cop->pclk_div,
1720 cop->l2clk, cop->l2clk ? "pclk" : "NULL",
1721 cop->l2clk_div,
1722 cop->pdclk, cop->l2clk ? "l2clk" : "pclk",
1723 cop->pdclk_div,
1724 cop->baclk, cop->l2clk ? "l2clk" : "pclk",
1725 cop->baclk_div,
1726 cop->periphclk,
1727 cop->periphclk ? "pclk" : "NULL",
1728 cop->periphclk_div);
1729
1730 /* calc this op's voltage req */
1731 cop->volts = cal_comp_volts_req(CORE, cop->pclk);
1732 }
1733 /* override cpu_opt_size with real support tbl */
1734 cur_platform_opt->cpu_opt_size = idx;
1735}
1736
1737static void __init_ddr_axi_opt(void)
1738{
1739 struct ddr_opt *ddr_opt, *ddr_cop;
1740 struct axi_opt *axi_opt, *axi_cop;
1741 union dfc_level_reg value;
1742 unsigned int ddr_opt_size = 0, axi_opt_size = 0, i;
1743
1744 ddr_opt = cur_platform_opt->ddr_opt;
1745 ddr_opt_size = cur_platform_opt->ddr_opt_size;
1746 axi_opt = cur_platform_opt->axi_opt;
1747 axi_opt_size = cur_platform_opt->axi_opt_size;
1748
1749 debug("dclk(src:sel,div)\n");
1750 for (i = 0; i < ddr_opt_size; i++) {
1751 ddr_cop = &ddr_opt[i];
1752 ddr_cop->ddr_clk_src = ddr_sel2_srcrate(ddr_cop->ddr_clk_sel);
1753 BUG_ON(ddr_cop->ddr_clk_src < 0);
1754 ddr_cop->dclk_div =
1755 ddr_cop->ddr_clk_src / (2 * ddr_cop->dclk) - 1;
1756 debug("%d(%d:%d,%d)\n",
1757 ddr_cop->dclk, ddr_cop->ddr_clk_src,
1758 ddr_cop->ddr_clk_sel, ddr_cop->dclk_div);
1759
1760 if (hwdfc_enable) {
1761 value.v = __raw_readl(DFC_LEVEL(i));
1762 value.b.dclksel = ddr_cop->ddr_clk_sel;
1763 value.b.ddr_clk_div = ddr_cop->dclk_div;
1764 value.b.mc_table_num = ddr_cop->ddr_tbl_index;
1765 value.b.volt_level = 0;
1766 __raw_writel(value.v, DFC_LEVEL(i));
1767 }
1768
1769 /* calc this op's voltage req */
1770 ddr_cop->volts = cal_comp_volts_req(DDR, ddr_cop->dclk);
1771 }
1772
1773 debug("aclk(src:sel,div)\n");
1774 for (i = 0; i < axi_opt_size; i++) {
1775 axi_cop = &axi_opt[i];
1776 axi_cop->axi_clk_src = axi_sel2_srcrate(axi_cop->axi_clk_sel);
1777 BUG_ON(axi_cop->axi_clk_src < 0);
1778 axi_cop->aclk_div =
1779 axi_cop->axi_clk_src / axi_cop->aclk - 1;
1780 debug("%d(%d:%d,%d)\n",
1781 axi_cop->aclk, axi_cop->axi_clk_src,
1782 axi_cop->axi_clk_sel, axi_cop->aclk_div);
1783
1784 /* calc this op's voltage req */
1785 axi_cop->volts = cal_comp_volts_req(AXI, axi_cop->aclk);
1786 }
1787}
1788
1789static void __init_fc_setting(void)
1790{
1791 unsigned int regval;
1792 union pmua_cc cc_cp;
1793 union pmua_cc_ap cc_ap;
1794 /*
1795 * enable AP FC done interrupt for one step,
1796 * while not use three interrupts by three steps
1797 */
1798 __raw_writel((1 << 1), APMU_IMR);
1799
1800 /* always vote for CP allow AP FC */
1801 cc_cp.v = __raw_readl(APMU_CP_CCR);
1802 cc_cp.b.core_allow_spd_chg = 1;
1803 __raw_writel(cc_cp.v, APMU_CP_CCR);
1804
1805 /* CA9 doesn't support halt acknowledge, mask it */
1806 regval = __raw_readl(APMU_DEBUG);
1807 regval |= (1 << 1);
1808 /*
1809 * Always set AP_WFI_FC and CP_WFI_FC, then PMU will
1810 * automaticlly send out clk-off ack when core is WFI
1811 */
1812 regval |= (1 << 21) | (1 << 22);
1813 /*
1814 * mask CP clk-off ack and cp halt ack for DDR/AXI FC
1815 * this bits should be unmasked after cp is released
1816 */
1817 regval |= (1 << 0) | (1 << 3);
1818 __raw_writel(regval, APMU_DEBUG);
1819
1820 /* always use async for DDR, AXI interface */
1821 cc_ap.v = __raw_readl(APMU_CCR);
1822 cc_ap.b.async5 = 1;
1823 cc_ap.b.async4 = 1;
1824 cc_ap.b.async3_1 = 1;
1825 cc_ap.b.async3 = 1;
1826 cc_ap.b.async2 = 1;
1827 cc_ap.b.async1 = 1;
1828 __raw_writel(cc_ap.v, APMU_CCR);
1829
1830 /* use to enable PU_CLK shared by USB, PLL2 and PLL3 */
1831 __raw_writel(__raw_readl(UTMI_CTRL) | (1 << 23), UTMI_CTRL);
1832
1833 /*
1834 * For helan2, vpu, gc, isp and LTE_DMA aclk need to be enabled and then disabled
1835 * so that MC internal gating logic can work.
1836 */
1837 if (cpu_is_pxa1U88()) {
1838 /* vpu */
1839 regval = __raw_readl(APMU_REG(0x0A4));
1840 __raw_writel(regval | (0x1 | 0x1 << 3), APMU_REG(0x0A4));
1841 regval = __raw_readl(APMU_REG(0x0A4));
1842 __raw_writel(regval & ~(0x1 | 0x1 << 3), APMU_REG(0x0A4));
1843 /* gc */
1844 regval = __raw_readl(APMU_REG(0x0F4));
1845 __raw_writel(regval | (0x1 | 0x1 << 3), APMU_REG(0x0F4));
1846 regval = __raw_readl(APMU_REG(0x0F4));
1847 __raw_writel(regval & ~(0x1 | 0x1 << 3), APMU_REG(0x0F4));
1848 /* isp */
1849 regval = __raw_readl(APMU_REG(0x038));
1850 __raw_writel(regval | (0x1 << 16 | 0x1 << 17), APMU_REG(0x038));
1851 regval = __raw_readl(APMU_REG(0x038));
1852 __raw_writel(regval & ~(0x1 << 16 | 0x1 << 17), APMU_REG(0x038));
1853 /* LTE_DMA */
1854 regval = __raw_readl(APMU_REG(0x048));
1855 __raw_writel(regval | (0x1 | 0x1 << 1), APMU_REG(0x048));
1856 regval = __raw_readl(APMU_REG(0x048));
1857 __raw_writel(regval & ~(0x1 | 0x1 << 1), APMU_REG(0x048));
1858 }
1859
1860 /* enable all MCK and AXI fabric dynamic clk gating */
1861 regval = __raw_readl(MC_CONF);
1862 /* enable dclk gating */
1863 regval &= ~(1 << 19);
1864 /* enable 1x2 fabric AXI clock dynamic gating */
1865 regval |= (0xff << 8) | /* MCK5 P0~P7*/
1866 (1 << 16) | /* CP 2x1 fabric*/
1867 (1 << 17) | (1 << 18) | /* AP&CP */
1868 (1 << 20) | (1 << 21) | /* SP&CSAP 2x1 fabric */
1869 (1 << 26) | (1 << 27) | /* Fabric 0/1 */
1870 (1 << 29) | (1 << 30); /* CA7 2x1 fabric */
1871 __raw_writel(regval, MC_CONF);
1872
1873 /* enable MCK4 AHB clock */
1874 __raw_writel(0x3, APMU_MCK4_CTRL);
1875}
1876
1877static struct cpu_opt *cpu_rate2_op_ptr
1878 (unsigned int rate, unsigned int *index)
1879{
1880 unsigned int idx = 0;
1881 struct cpu_opt *cop;
1882
1883 list_for_each_entry(cop, &core_op_list, node) {
1884 if ((cop->pclk >= rate) ||
1885 list_is_last(&cop->node, &core_op_list))
1886 break;
1887 idx++;
1888 }
1889
1890 *index = idx;
1891 return cop;
1892}
1893
1894static unsigned int cpu_get_oprateandvl(unsigned int index,
1895 unsigned int *volts)
1896{
1897 unsigned int idx = 0;
1898 struct cpu_opt *cop;
1899
1900 list_for_each_entry(cop, &core_op_list, node) {
1901 if ((idx == index) ||
1902 list_is_last(&cop->node, &core_op_list))
1903 break;
1904 idx++;
1905 }
1906 *volts = cop->volts;
1907 return cop->pclk;
1908}
1909
1910static unsigned int ddr_rate2_op_index(unsigned int rate)
1911{
1912 unsigned int index;
1913 struct ddr_opt *op_array =
1914 cur_platform_opt->ddr_opt;
1915 unsigned int op_array_size =
1916 cur_platform_opt->ddr_opt_size;
1917
1918 if (unlikely(rate > op_array[op_array_size - 1].dclk))
1919 return op_array_size - 1;
1920
1921 for (index = 0; index < op_array_size; index++)
1922 if (op_array[index].dclk >= rate)
1923 break;
1924
1925 return index;
1926}
1927
1928static unsigned int ddr_get_oprateandvl(unsigned int index,
1929 unsigned int *volts)
1930{
1931 *volts = cur_platform_opt->ddr_opt[index].volts;
1932 return cur_platform_opt->ddr_opt[index].dclk;
1933}
1934
1935static unsigned int axi_rate2_op_index(unsigned int rate)
1936{
1937 unsigned int index;
1938 struct axi_opt *op_array =
1939 cur_platform_opt->axi_opt;
1940 unsigned int op_array_size =
1941 cur_platform_opt->axi_opt_size;
1942
1943 if (unlikely(rate > op_array[op_array_size - 1].aclk))
1944 return op_array_size - 1;
1945
1946 for (index = 0; index < op_array_size; index++)
1947 if (op_array[index].aclk >= rate)
1948 break;
1949
1950 return index;
1951}
1952
1953static unsigned int axi_get_oprateandvl(unsigned int index,
1954 unsigned int *volts)
1955{
1956 *volts = cur_platform_opt->axi_opt[index].volts;
1957 return cur_platform_opt->axi_opt[index].aclk;
1958}
1959
1960static unsigned int cpu_sel2_srcrate(enum ap_clk_sel ap_sel)
1961{
1962 if (ap_sel == AP_CLK_SRC_PLL1_624)
1963 return 624;
1964 else if (ap_sel == AP_CLK_SRC_PLL1_1248)
1965 return 1248;
1966 else if (ap_sel == AP_CLK_SRC_PLL2)
1967 return cur_platform_opt->pll2freq;
1968 else if (ap_sel == AP_CLK_SRC_PLL1_832)
1969 return 832;
1970 else if (ap_sel == AP_CLK_SRC_PLL3P)
1971 return cur_platform_opt->pll3pfreq;
1972
1973 printf("%s bad ap_clk_sel %d\n", __func__, ap_sel);
1974 return -ENOENT;
1975}
1976
1977static unsigned int ddr_sel2_srcrate(enum ddr_clk_sel ddr_sel)
1978{
1979 if (ddr_sel == DDR_CLK_SRC_PLL1_624)
1980 return 624;
1981 else if (ddr_sel == DDR_CLK_SRC_PLL1_832)
1982 return 832;
1983 else if (ddr_sel == DDR_CLK_SRC_PLL2)
1984 return cur_platform_opt->pll2freq;
1985 else if (ddr_sel == DDR_CLK_SRC_PLL4)
1986 return cur_platform_opt->pll4freq;
1987 else if (ddr_sel == DDR_CLK_SRC_PLL3P)
1988 return cur_platform_opt->pll3pfreq;
1989
1990 printf("%s bad ddr_sel %d\n", __func__, ddr_sel);
1991 return -ENOENT;
1992}
1993
1994static unsigned int axi_sel2_srcrate(enum axi_clk_sel axi_sel)
1995{
1996 if (axi_sel == AXI_CLK_SRC_PLL1_416)
1997 return 416;
1998 else if (axi_sel == AXI_CLK_SRC_PLL1_624)
1999 return 624;
2000 else if (axi_sel == AXI_CLK_SRC_PLL2)
2001 return cur_platform_opt->pll2freq;
2002 else if (axi_sel == AXI_CLK_SRC_PLL2P)
2003 return cur_platform_opt->pll2pfreq;
2004
2005 printf("%s bad axi_sel %d\n", __func__, axi_sel);
2006 return -ENOENT;
2007}
2008
2009static unsigned int ap_clk_enable(enum ap_clk_sel ap_sel)
2010{
2011 if (ap_sel == AP_CLK_SRC_PLL2)
2012 turn_on_pll(PLL2);
2013 else if (ap_sel == AP_CLK_SRC_PLL3P)
2014 turn_on_pll(PLL3);
2015 return 0;
2016}
2017
2018static unsigned int ap_clk_disable(enum ap_clk_sel ap_sel)
2019{
2020 if (ap_sel == AP_CLK_SRC_PLL2)
2021 turn_off_pll(PLL2);
2022 else if (ap_sel == AP_CLK_SRC_PLL3P)
2023 turn_off_pll(PLL3);
2024 return 0;
2025}
2026
2027static unsigned int ddr_clk_enable(enum ddr_clk_sel ddr_sel)
2028{
2029 if (ddr_sel == DDR_CLK_SRC_PLL2)
2030 turn_on_pll(PLL2);
2031 else if (ddr_sel == DDR_CLK_SRC_PLL4)
2032 turn_on_pll(PLL4);
2033 else if (ddr_sel == DDR_CLK_SRC_PLL3P)
2034 turn_on_pll(PLL3);
2035 return 0;
2036}
2037
2038static unsigned int ddr_clk_disable(enum ddr_clk_sel ddr_sel)
2039{
2040 if (ddr_sel == DDR_CLK_SRC_PLL2)
2041 turn_off_pll(PLL2);
2042 else if (ddr_sel == DDR_CLK_SRC_PLL4)
2043 turn_off_pll(PLL4);
2044 else if (ddr_sel == DDR_CLK_SRC_PLL3P)
2045 turn_off_pll(PLL3);
2046 return 0;
2047}
2048
2049static unsigned int axi_clk_enable(enum axi_clk_sel axi_sel)
2050{
2051 if (axi_sel == AXI_CLK_SRC_PLL2 ||
2052 axi_sel == AXI_CLK_SRC_PLL2P)
2053 turn_on_pll(PLL2);
2054 return 0;
2055}
2056
2057static unsigned int axi_clk_disable(enum axi_clk_sel axi_sel)
2058{
2059 if (axi_sel == AXI_CLK_SRC_PLL2 ||
2060 axi_sel == AXI_CLK_SRC_PLL2P)
2061 turn_off_pll(PLL2);
2062 return 0;
2063}
2064
2065static int fc_lock_ref_cnt;
2066static void get_fc_lock(void)
2067{
2068 union pmua_dm_cc dm_cc_ap;
2069
2070 fc_lock_ref_cnt++;
2071
2072 if (fc_lock_ref_cnt == 1) {
2073 int timeout = 100000;
2074
2075 /* AP-CP FC mutual exclusion */
2076 dm_cc_ap.v = __raw_readl(APMU_CCSR);
2077 while (dm_cc_ap.b.cp_rd_status && timeout) {
2078 dm_cc_ap.v = __raw_readl(APMU_CCSR);
2079 timeout--;
2080 }
2081 if (timeout <= 0) {
2082 printf("cp does not release its fc lock\n");
2083 BUG();
2084 }
2085 }
2086}
2087
2088static void put_fc_lock(void)
2089{
2090 union pmua_cc cc_ap;
2091
2092 fc_lock_ref_cnt--;
2093
2094 if (fc_lock_ref_cnt < 0)
2095 printf("unmatched put_fc_lock\n");
2096
2097 if (fc_lock_ref_cnt == 0) {
2098 /* write 1 to MOH_RD_ST_CLEAR to clear MOH_RD_STATUS */
2099 cc_ap.v = __raw_readl(APMU_CCR);
2100 cc_ap.b.core_rd_st_clear = 1;
2101 __raw_writel(cc_ap.v, APMU_CCR);
2102 cc_ap.b.core_rd_st_clear = 0;
2103 __raw_writel(cc_ap.v, APMU_CCR);
2104 }
2105}
2106
2107static void get_cur_cpu_op(struct cpu_opt *cop)
2108{
2109 union pmua_pllsel pllsel;
2110 union pmua_dm_cc dm_cc_ap;
2111 union pmua_dm_cc2 dm_cc2_ap;
2112
2113 get_fc_lock();
2114
2115 dm_cc_ap.v = __raw_readl(APMU_CCSR);
2116 dm_cc2_ap.v = __raw_readl(APMU_CC2SR);
2117 pllsel.v = __raw_readl(APMU_PLL_SEL_STATUS);
2118
2119 /* PLL Clock Select Status Register
2120 * when APMU_PLL_SEL_STATUS[4:5] = 0x1, ap clk source depand on
2121 * APMU_PLL_SEL_STATUS[8] bit status. If APMU_PLL_SEL_STATUS[8]
2122 * is 0x0 ap clk is divided from PLL1_1248M or ap clk use PLL3P
2123 * as clk source.
2124 */
2125 if ((pllsel.b.apclksel1 == 0x1) &&
2126 (pllsel.b.apclksel2 == 0x1)) {
2127 cop->ap_clk_src = cpu_sel2_srcrate(AP_CLK_SRC_PLL3P);
2128 cop->ap_clk_sel = AP_CLK_SRC_PLL3P;
2129 } else {
2130 cop->ap_clk_src = cpu_sel2_srcrate(pllsel.b.apclksel1);
2131 cop->ap_clk_sel = pllsel.b.apclksel1;
2132 }
2133 cop->pclk = cop->ap_clk_src / (dm_cc_ap.b.core_clk_div + 1);
2134 if (cop->l2clk) {
2135 cop->l2clk = cop->pclk / (dm_cc_ap.b.l2_clk_div + 1);
2136 cop->pdclk = cop->l2clk / (dm_cc_ap.b.bus_mc_clk_div + 1);
2137 cop->baclk = cop->l2clk / (dm_cc_ap.b.biu_clk_div + 1);
2138 } else {
2139 cop->pdclk = cop->pclk / (dm_cc_ap.b.bus_mc_clk_div + 1);
2140 cop->baclk = cop->pclk / (dm_cc_ap.b.biu_clk_div + 1);
2141 }
2142 if (cop->periphclk)
2143 cop->periphclk =
2144 cop->pclk / (dm_cc2_ap.b.peri_clk_div + 1) / 4;
2145
2146 put_fc_lock();
2147}
2148
2149static void get_cur_ddr_op(struct ddr_opt *cop)
2150{
2151 union pmua_pllsel pllsel;
2152 union pmua_dm_cc dm_cc_ap;
2153 enum ddr_clk_sel ddr_sel;
2154 get_fc_lock();
2155
2156 dm_cc_ap.v = __raw_readl(APMU_CCSR);
2157 pllsel.v = __raw_readl(APMU_PLL_SEL_STATUS);
2158 ddr_sel = pllsel.b.ddrclksel1 | (pllsel.b.ddrclksel2 << 2);
2159 cop->ddr_clk_src = ddr_sel2_srcrate(ddr_sel);
2160 cop->ddr_clk_sel = ddr_sel;
2161 cop->dclk = cop->ddr_clk_src / (dm_cc_ap.b.ddr_clk_div + 1) / 2;
2162
2163 put_fc_lock();
2164}
2165
2166static void get_cur_axi_op(struct axi_opt *cop)
2167{
2168 union pmua_pllsel pllsel;
2169 union pmua_dm_cc dm_cc_ap;
2170
2171 get_fc_lock();
2172
2173 dm_cc_ap.v = __raw_readl(APMU_CCSR);
2174 pllsel.v = __raw_readl(APMU_PLL_SEL_STATUS);
2175
2176 cop->axi_clk_src = axi_sel2_srcrate(pllsel.b.axiclksel);
2177 cop->axi_clk_sel = pllsel.b.axiclksel;
2178 cop->aclk = cop->axi_clk_src / (dm_cc_ap.b.bus_clk_div + 1);
2179
2180 put_fc_lock();
2181}
2182
2183static void wait_for_fc_done(void)
2184{
2185 int timeout = 1000000;
2186 while (!((1 << 1) & __raw_readl(APMU_ISR)) && timeout)
2187 timeout--;
2188 if (timeout <= 0)
2189 printf("AP frequency change timeout! ISR = 0x%x\n",
2190 __raw_readl(APMU_ISR));
2191 __raw_writel(0x0, APMU_ISR);
2192}
2193
2194static void set_ap_clk_sel(struct cpu_opt *top)
2195{
2196 u32 fcap, value;
2197 fcap = top->ap_clk_sel & MPMU_FCAP_MASK;
2198 debug_wt_reg(fcap, MPMU_FCAP);
2199 value = __raw_readl(MPMU_FCAP);
2200 if (value != fcap)
2201 printf("CORE FCAP Write failure: target 0x%X, final value 0x%X\n",
2202 fcap, value);
2203}
2204
2205static void set_ddr_clk_sel(struct ddr_opt *top)
2206{
2207 u32 fcdclk, value;
2208 fcdclk = top->ddr_clk_sel & MPMU_FCDCLK_MASK;
2209 debug_wt_reg(fcdclk, MPMU_FCDCLK);
2210 value = __raw_readl(MPMU_FCDCLK);
2211 if (value != fcdclk)
2212 printf("DDR FCDCLK Write failure: target 0x%X, final value 0x%X\n",
2213 fcdclk, value);
2214}
2215
2216static void set_axi_clk_sel(struct axi_opt *top)
2217{
2218 u32 fcaclk, value;
2219 fcaclk = top->axi_clk_sel & MPMU_FCACLK_MASK;
2220 debug_wt_reg(fcaclk, MPMU_FCACLK);
2221 value = __raw_readl(MPMU_FCACLK);
2222 if (value != fcaclk)
2223 printf("AXI FCACLK Write failure: target 0x%X, final value 0x%X\n",
2224 fcaclk, value);
2225}
2226
2227static void set_periph_clk_div(struct cpu_opt *top)
2228{
2229 union pmua_cc2 cc_ap2;
2230
2231 cc_ap2.v = __raw_readl(APMU_CC2R);
2232 cc_ap2.b.peri_clk_div = top->periphclk_div;
2233 debug_wt_reg(cc_ap2.v, APMU_CC2R);
2234}
2235
2236static void set_ddr_tbl_index(unsigned int index)
2237{
2238 unsigned int regval;
2239
2240 /* APMU_MC_HW_SLP_TYPE[3:7] store the table number for mc5 */
2241 index &= 0x1F;
2242 regval = __raw_readl(APMU_MC_HW_SLP_TYPE);
2243 regval &= ~(0x1 << 10); /* enable tbl based FC */
2244 regval &= ~(0x1F << 3); /* clear ddr tbl index */
2245 regval |= (index << 3);
2246 debug_wt_reg(regval, APMU_MC_HW_SLP_TYPE);
2247}
2248
2249/*
2250 * Sequence of changing RTC on the fly
2251 * RTC_lowpp means RTC is better for lowPP
2252 * RTC_highpp means RTC is better for highPP
2253 *
2254 * lowPP -> highPP:
2255 * 1) lowPP(RTC_lowpp) works at Vnom_lowPP(RTC_lowpp)
2256 * 2) Voltage increases from Vnom_lowPP(RTC_lowpp) to
2257 * Vnom_highPP(RTC_highpp)
2258 * 3) RTC changes from RTC_lowpp to RTC_highpp, lowPP(RTC_highpp)
2259 * could work at Vnom_highpp(RTC_highpp) as Vnom_highpp(RTC_highpp)
2260 * >= Vnom_lowpp(RTC_highpp)
2261 * 4) Core freq-chg from lowPP(RTC_highpp) to highPP(RTC_highpp)
2262 *
2263 * highPP -> lowPP:
2264 * 1) highPP(RTC_highpp) works at Vnom_highPP(RTC_highpp)
2265 * 2) Core freq-chg from highPP(RTC_highpp) to lowPP(RTC_highpp),
2266 * voltage could meet requirement as Vnom_highPP(RTC_highpp) >=
2267 * Vnom_lowpp(RTC_highpp)
2268 * 3) RTC changes from RTC_highpp to RTC_lowpp. Vnom_lowpp(RTC_lowpp)
2269 * < Vnom_lowpp(RTC_highpp), the voltage is ok
2270 * 4) voltage decreases from Vnom_highPP(RTC_highpp) to
2271 * Vnom_lowPP(RTC_lowpp)
2272 */
2273static void core_fc_seq(struct cpu_opt *cop,
2274 struct cpu_opt *top)
2275{
2276 union pmua_cc cc_cp;
2277 union pmua_cc_ap cc_ap;
2278
2279 /*
2280 * add check here to avoid the case default boot up PP
2281 * has different pdclk and paclk definition with PP used
2282 * in production
2283 */
2284 if ((cop->ap_clk_src == top->ap_clk_src) &&
2285 (cop->pclk == top->pclk) &&
2286 (cop->pdclk == top->pdclk) &&
2287 (cop->baclk == top->baclk)) {
2288 printf("current rate = target rate!\n");
2289 return;
2290 }
2291
2292 /* low -> high */
2293 if (cop->pclk < top->pclk) {
2294 __raw_writel(top->l1_rtc,
2295 CIU_CA9_CPU_CONF_SRAM_0);
2296 __raw_writel(top->l2_rtc,
2297 CIU_CA9_CPU_CONF_SRAM_1);
2298 }
2299
2300 /* 0) Pre FC : check CP allow AP FC voting */
2301 cc_cp.v = __raw_readl(APMU_CP_CCR);
2302 if (unlikely(!cc_cp.b.core_allow_spd_chg)) {
2303 printf("%s CP doesn't allow AP FC!\n",
2304 __func__);
2305 cc_cp.b.core_allow_spd_chg = 1;
2306 __raw_writel(cc_cp.v, APMU_CP_CCR);
2307 }
2308
2309 /* 1) Pre FC : AP votes allow FC */
2310 cc_ap.v = __raw_readl(APMU_CCR);
2311 cc_ap.b.core_allow_spd_chg = 1;
2312
2313 /* 2) issue core FC */
2314 /* 2.1) set pclk src */
2315 set_ap_clk_sel(top);
2316 /* 2.2) select div for pclk, l2clk, pdclk, baclk */
2317 cc_ap.b.core_clk_div = top->pclk_div;
2318 if (top->l2clk)
2319 cc_ap.b.l2_clk_div = top->l2clk_div;
2320 cc_ap.b.bus_mc_clk_div = top->pdclk_div;
2321 cc_ap.b.biu_clk_div = top->baclk_div;
2322 /* 2.3) set periphclk div */
2323 if (top->periphclk)
2324 set_periph_clk_div(top);
2325
2326 cc_ap.b.core_freq_chg_req = 1;
2327 /* used only for core FC, will NOT trigger fc_sm */
2328 /* cc_ap.b.core_dyn_fc = 1; */
2329
2330 /* 2.4) set div and FC req trigger core FC */
2331 debug_wt_reg(cc_ap.v, APMU_CCR);
2332 wait_for_fc_done();
2333
2334 /* 3) Post FC : AP clear allow FC voting */
2335 cc_ap.v = __raw_readl(APMU_CCR);
2336 cc_ap.b.core_allow_spd_chg = 0;
2337 __raw_writel(cc_ap.v, APMU_CCR);
2338
2339 /* high -> low */
2340 if (cop->pclk > top->pclk) {
2341 __raw_writel(top->l1_rtc,
2342 CIU_CA9_CPU_CONF_SRAM_0);
2343 __raw_writel(top->l2_rtc,
2344 CIU_CA9_CPU_CONF_SRAM_1);
2345 }
2346}
2347
2348static int set_core_freq(struct cpu_opt *old, struct cpu_opt *new)
2349{
2350 struct cpu_opt cop;
2351 int ret = 0;
2352
2353 printf("CORE FC start: %u -> %u\n",
2354 old->pclk, new->pclk);
2355 get_fc_lock();
2356
2357 memcpy(&cop, old, sizeof(struct cpu_opt));
2358#if 0
2359 /*
2360 * We do NOT check it here as system boot up
2361 * PP may be has different pdclk,paclk with
2362 * PP table we defined.Only check the freq
2363 * after every FC.
2364 */
2365 get_cur_cpu_op(&cop);
2366 if (unlikely((cop.ap_clk_src != old->ap_clk_src) ||
2367 (cop.pclk != old->pclk) ||
2368 (cop.l2clk != old->l2clk) ||
2369 (cop.pdclk != old->pdclk) ||
2370 (cop.baclk != old->baclk) ||
2371 (cop.periphclk != old->periphclk))) {
2372 printf("psrc pclk l2clk pdclk baclk periphclk\n");
2373 printf("OLD %d %d %d %d %d %d\n", old->ap_clk_src,
2374 old->pclk, old->l2clk, old->pdclk, old->baclk,
2375 old->periphclk);
2376 printf("CUR %d %d %d %d %d %d\n", cop.ap_clk_src,
2377 cop.pclk, cop.l2clk, cop.pdclk, cop.baclk,
2378 cop.periphclk);
2379 printf("NEW %d %d %d %d %d %d\n", new->ap_clk_src,
2380 new->pclk, new->l2clk, new->pdclk, new->baclk,
2381 new->periphclk);
2382 }
2383#endif
2384 ap_clk_enable(new->ap_clk_sel);
2385 core_fc_seq(&cop, new);
2386
2387 memcpy(&cop, new, sizeof(struct cpu_opt));
2388 get_cur_cpu_op(&cop);
2389 if (unlikely((cop.ap_clk_src != new->ap_clk_src) ||
2390 (cop.pclk != new->pclk) ||
2391 (cop.l2clk != new->l2clk) ||
2392 (cop.pdclk != new->pdclk) ||
2393 (cop.baclk != new->baclk) ||
2394 (cop.periphclk != new->periphclk))) {
2395 printf("unsuccessful frequency change!\n");
2396 printf("psrc pclk l2clk pdclk baclk periphclk\n");
2397 printf("CUR %d %d %d %d %d %d\n", cop.ap_clk_src,
2398 cop.pclk, cop.l2clk, cop.pdclk, cop.baclk,
2399 cop.periphclk);
2400 printf("NEW %d %d %d %d %d %d\n", new->ap_clk_src,
2401 new->pclk, new->l2clk, new->pdclk, new->baclk,
2402 new->periphclk);
2403 ret = -EAGAIN;
2404 ap_clk_disable(new->ap_clk_sel);
2405 goto out;
2406 }
2407
2408 ap_clk_disable(old->ap_clk_sel);
2409out:
2410 put_fc_lock();
2411 printf("CORE FC end: %u -> %u\n",
2412 old->pclk, new->pclk);
2413 return ret;
2414}
2415
2416static int cpu_setrate(unsigned long rate)
2417{
2418 struct cpu_opt *md_new, *md_old;
2419 unsigned int index;
2420 int ret = 0;
2421
2422 if (unlikely(!cur_cpu_op))
2423 cur_cpu_op = &helan2_cpu_bootop;
2424 md_new = cpu_rate2_op_ptr(rate, &index);
2425 md_old = cur_cpu_op;
2426
2427 ret = set_core_freq(md_old, md_new);
2428
2429 if (ret)
2430 goto out;
2431 cur_cpu_op = md_new;
2432out:
2433 return ret;
2434}
2435
2436static void ddr_fc_seq(struct ddr_opt *cop,
2437 struct ddr_opt *top)
2438{
2439 union pmua_cc cc_cp;
2440 union pmua_cc_ap cc_ap;
2441 unsigned int ddr_fc = 0;
2442
2443 /* 0) Pre FC : check CP allow AP FC voting */
2444 cc_cp.v = __raw_readl(APMU_CP_CCR);
2445 if (unlikely(!cc_cp.b.core_allow_spd_chg)) {
2446 printf("%s CP doesn't allow AP FC!\n",
2447 __func__);
2448 cc_cp.b.core_allow_spd_chg = 1;
2449 __raw_writel(cc_cp.v, APMU_CP_CCR);
2450 }
2451
2452 /* 1) Pre FC : AP votes allow FC */
2453 cc_ap.v = __raw_readl(APMU_CCR);
2454 cc_ap.b.core_allow_spd_chg = 1;
2455
2456 /* 2) issue DDR FC */
2457 if ((cop->ddr_clk_src != top->ddr_clk_src) ||
2458 (cop->dclk != top->dclk)) {
2459 /* 2.1) set dclk src */
2460 set_ddr_clk_sel(top);
2461 /* 2.2) enable tbl based FC and set DDR tbl num */
2462 set_ddr_tbl_index(top->ddr_tbl_index);
2463 /* 2.3) select div for dclk */
2464 cc_ap.b.ddr_clk_div = top->dclk_div;
2465 /* 2.4) select ddr FC req bit */
2466 cc_ap.b.ddr_freq_chg_req = 1;
2467 ddr_fc = 1;
2468 }
2469
2470 /* 3) set div and FC req bit trigger DDR/AXI FC */
2471 if (ddr_fc) {
2472 debug_wt_reg(cc_ap.v, APMU_CCR);
2473 wait_for_fc_done();
2474 }
2475
2476 /* 4) Post FC : AP clear allow FC voting */
2477 cc_ap.v = __raw_readl(APMU_CCR);
2478 cc_ap.b.core_allow_spd_chg = 0;
2479 __raw_writel(cc_ap.v, APMU_CCR);
2480}
2481
2482static void axi_fc_seq(struct axi_opt *cop,
2483 struct axi_opt *top)
2484{
2485 union pmua_cc cc_cp;
2486 union pmua_cc_ap cc_ap;
2487 unsigned int axi_fc = 0;
2488
2489 /* 0) Pre FC : check CP allow AP FC voting */
2490 cc_cp.v = __raw_readl(APMU_CP_CCR);
2491 if (unlikely(!cc_cp.b.core_allow_spd_chg)) {
2492 printf("%s CP doesn't allow AP FC!\n",
2493 __func__);
2494 cc_cp.b.core_allow_spd_chg = 1;
2495 __raw_writel(cc_cp.v, APMU_CP_CCR);
2496 }
2497
2498 /* 1) Pre FC : AP votes allow FC */
2499 cc_ap.v = __raw_readl(APMU_CCR);
2500 cc_ap.b.core_allow_spd_chg = 1;
2501
2502 /* 2) issue AXI FC */
2503 if ((cop->axi_clk_src != top->axi_clk_src) ||
2504 (cop->aclk != top->aclk)) {
2505 /* 3.1) set aclk src */
2506 set_axi_clk_sel(top);
2507 /* 3.2) select div for aclk */
2508 cc_ap.b.bus_clk_div = top->aclk_div;
2509 /* 3.3) select axi FC req bit */
2510 cc_ap.b.bus_freq_chg_req = 1;
2511 axi_fc = 1;
2512 }
2513
2514 /* 3) set div and FC req bit trigger DDR/AXI FC */
2515 if (axi_fc) {
2516 debug_wt_reg(cc_ap.v, APMU_CCR);
2517 wait_for_fc_done();
2518 }
2519
2520 /* 4) Post FC : AP clear allow FC voting */
2521 cc_ap.v = __raw_readl(APMU_CCR);
2522 cc_ap.b.core_allow_spd_chg = 0;
2523 __raw_writel(cc_ap.v, APMU_CCR);
2524}
2525
2526static void __ddr_hwdfc_seq(unsigned int level)
2527{
2528 union dfc_ap dfc_ap;
2529 union dfc_status status;
2530 dfc_ap.v = __raw_readl(DFC_AP);
2531 dfc_ap.b.freq_level = level;
2532 dfc_ap.b.dfc_req = 1;
2533 __raw_writel(dfc_ap.v, DFC_AP);
2534 wait_for_fc_done();
2535 status.v = __raw_readl(DFC_STATUS);
2536 if (unlikely(status.b.cfl != level)) {
2537 printf("HW-DFC failed! expect LV %d, actual LV %d\n",
2538 level, status.b.cfl);
2539 printf("HW_AP: %x, HW_STATUS: %x\n",
2540 __raw_readl(DFC_AP), status.v);
2541 }
2542}
2543
2544
2545static int first_ddr_fc;
2546static void ddr_hwdfc_seq(struct ddr_opt *cop,
2547 struct ddr_opt *top)
2548{
2549 /*
2550 * HW thinks default DFL is 0, we have to make sure HW
2551 * get the correct DFL by first change it to 0, then change
2552 * it to current DFL
2553 */
2554 if (unlikely(!first_ddr_fc)) {
2555 __ddr_hwdfc_seq(0);
2556 __ddr_hwdfc_seq(cop->ddr_freq_level);
2557 first_ddr_fc = 1;
2558 }
2559
2560 __ddr_hwdfc_seq(top->ddr_freq_level);
2561}
2562
2563static int set_ddr_freq(struct ddr_opt *old,
2564 struct ddr_opt *new)
2565{
2566 struct ddr_opt cop;
2567 int ret = 0, errflag = 0;
2568
2569 printf("DDR FC start: DDR %u -> %u\n",
2570 old->dclk, new->dclk);
2571
2572 if (!hwdfc_enable)
2573 get_fc_lock();
2574
2575 memcpy(&cop, old, sizeof(struct ddr_opt));
2576
2577 ddr_clk_enable(new->ddr_clk_sel);
2578
2579 if (hwdfc_enable)
2580 ddr_hwdfc_seq(&cop, new);
2581 else
2582 ddr_fc_seq(&cop, new);
2583
2584 memcpy(&cop, new, sizeof(struct ddr_opt));
2585 get_cur_ddr_op(&cop);
2586 if (unlikely((cop.ddr_clk_src != new->ddr_clk_src) ||
2587 (cop.dclk != new->dclk))) {
2588 ddr_clk_disable(new->ddr_clk_sel);
2589 errflag = 1;
2590 }
2591 if (unlikely(errflag)) {
2592 printf("DDR:unsuccessful frequency change!\n");
2593 printf(" dsrc dclk\n");
2594 printf("CUR %d %d\n", cop.ddr_clk_src, cop.dclk);
2595 printf("NEW %d %d\n", new->ddr_clk_src, new->dclk);
2596 ret = -EAGAIN;
2597 goto out;
2598 }
2599
2600 ddr_clk_disable(old->ddr_clk_sel);
2601out:
2602 if (!hwdfc_enable)
2603 put_fc_lock();
2604 printf("DDR FC end: DDR %u -> %u\n", old->dclk, new->dclk);
2605 return ret;
2606}
2607
2608static int set_axi_freq(struct axi_opt *old,
2609 struct axi_opt *new)
2610{
2611 struct axi_opt cop;
2612 int ret = 0, errflag = 0;
2613
2614 printf("AXI FC start: AXI %u -> %u\n",
2615 old->aclk, new->aclk);
2616 get_fc_lock();
2617
2618 memcpy(&cop, old, sizeof(struct axi_opt));
2619 axi_clk_enable(new->axi_clk_sel);
2620 axi_fc_seq(&cop, new);
2621
2622 memcpy(&cop, new, sizeof(struct axi_opt));
2623 get_cur_axi_op(&cop);
2624 if (unlikely((cop.axi_clk_src != new->axi_clk_src) ||
2625 (cop.aclk != new->aclk))) {
2626 axi_clk_disable(new->axi_clk_sel);
2627 errflag = 1;
2628 }
2629 if (unlikely(errflag)) {
2630 printf("AXI:unsuccessful frequency change!\n");
2631 printf("asrc aclk\n");
2632 printf("CUR %d %d\n", cop.axi_clk_src, cop.aclk);
2633 printf("NEW %d %d\n", new->axi_clk_src, new->aclk);
2634 ret = -EAGAIN;
2635 goto out;
2636 }
2637
2638 axi_clk_disable(old->axi_clk_sel);
2639out:
2640 put_fc_lock();
2641 printf("AXI FC end: AXI %u -> %u\n",
2642 old->aclk, new->aclk);
2643 return ret;
2644}
2645
2646static int ddr_setrate(unsigned long rate)
2647{
2648 struct ddr_opt *md_new, *md_old;
2649 unsigned int index;
2650 int ret = 0;
2651 struct ddr_opt *op_array =
2652 cur_platform_opt->ddr_opt;
2653
2654 if (unlikely(!cur_ddr_op))
2655 cur_ddr_op = &helan2_ddr_bootop;
2656
2657 index = ddr_rate2_op_index(rate);
2658 md_new = &op_array[index];
2659 md_old = cur_ddr_op;
2660
2661 ret = set_ddr_freq(md_old, md_new);
2662 if (ret)
2663 goto out;
2664 cur_ddr_op = md_new;
2665out:
2666 return ret;
2667}
2668
2669static int axi_setrate(unsigned long rate)
2670{
2671 struct axi_opt *md_new, *md_old;
2672 unsigned int index;
2673 int ret = 0;
2674 struct axi_opt *op_array =
2675 cur_platform_opt->axi_opt;
2676
2677 if (unlikely(!cur_axi_op))
2678 cur_axi_op = &helan2_axi_bootop;
2679
2680 index = axi_rate2_op_index(rate);
2681 md_new = &op_array[index];
2682 md_old = cur_axi_op;
2683
2684 ret = set_axi_freq(md_old, md_new);
2685 if (ret)
2686 goto out;
2687 cur_axi_op = md_new;
2688out:
2689 return ret;
2690}
2691
2692unsigned int get_max_cpurate(void)
2693{
2694 if (cur_platform_opt)
2695 return cur_platform_opt->df_max_cpurate;
2696 return 0;
2697}
2698
2699/*
2700 * This function is called from board level or cmd to
2701 * issue the core, ddr&axi frequency change.
2702 */
2703int setop(unsigned int pclk, unsigned int dclk, unsigned int aclk)
2704{
2705 u32 pidx, didx, aidx;
2706 u32 pvcore, dvcore, avcore, vcore, cur_volt;
2707 int ret = 0;
2708
2709 cpu_rate2_op_ptr(pclk, &pidx);
2710 didx = ddr_rate2_op_index(dclk);
2711 aidx = axi_rate2_op_index(aclk);
2712 cpu_get_oprateandvl(pidx, &pvcore);
2713 ddr_get_oprateandvl(didx, &dvcore);
2714 axi_get_oprateandvl(aidx, &avcore);
2715 vcore = max(pvcore, dvcore);
2716 vcore = max(vcore, avcore);
2717
2718 cur_volt = get_volt();
2719 printf("cur %umV, tgt %umV\n", cur_volt, vcore);
2720 if (vcore > cur_volt) {
2721 ret = set_volt(vcore);
2722 if (ret) {
2723 printf("Increase Vcore %umV->%umV failed!\n",
2724 cur_volt, vcore);
2725 return -1;
2726 } else
2727 printf("Increase Vcore %umV->%umV done!\n",
2728 cur_volt, vcore);
2729 }
2730
2731 ret |= ddr_setrate(dclk);
2732 ret |= axi_setrate(aclk);
2733 ret |= cpu_setrate(pclk);
2734 /* any failed, return without voltage change */
2735 if (ret)
2736 return 0;
2737
2738 if (vcore < cur_volt) {
2739 ret = set_volt(vcore);
2740 if (ret) {
2741 printf("Decrease Vcore %umV->%umV failed!\n",
2742 cur_volt, vcore);
2743 return -1;
2744 } else
2745 printf("Decrease Vcore %umV->%umV done!\n",
2746 cur_volt, vcore);
2747 }
2748 return 0;
2749}
2750
2751/* use to cal core/ddr/axi VL request */
2752static unsigned int cal_comp_volts_req(enum vcore_comps comp,
2753 unsigned int rate)
2754{
2755 unsigned int idx = 0;
2756 unsigned int vlreq = VL_MAX - 1;
2757
2758 if (!cur_platform_opt->freqs_cmb ||
2759 !cur_platform_opt->vm_millivolts) {
2760 printf("Fill volts req info at first!\n");
2761 return 0;
2762 }
2763
2764 if (comp > VM_RAIL_MAX) {
2765 printf("Bad paras! comp:%d\n", comp);
2766 goto out;
2767 }
2768
2769 for (idx = 0; idx < VL_MAX; idx++)
2770 if (rate <= cur_platform_opt->freqs_cmb[comp][idx])
2771 break;
2772
2773 if (idx == VL_MAX) {
2774 printf("Unsupported rate:%u, comp:%d\n", rate, comp);
2775 goto out;
2776 }
2777 vlreq = idx;
2778out:
2779 return cur_platform_opt->vm_millivolts[vlreq];
2780}
2781
2782static void __init_volts_info(int profile)
2783{
2784 int *vm_millivolts;
2785 unsigned int (*freqs_cmb)[VL_MAX];
2786
2787 /* FIXME: register platform info according to profile */
2788 vm_millivolts = vm_mv_helan2_svc[profile];
2789 freqs_cmb = freqs_cmb_helan2;
2790
2791 cur_platform_opt->vm_millivolts = vm_millivolts;
2792 cur_platform_opt->freqs_cmb = freqs_cmb;
2793
2794 return;
2795}
2796
2797/*
2798 * This function is called from board/CPU init level to initialize
2799 * the OP table/dvfs and frequency change related setting
2800 */
2801void helan2_fc_init(int ddr_mode)
2802{
2803 /* notes that below sequence has dependency */
2804 /* FIXME: enable it after verified due to reg address adjust */
2805 __init_read_ultinfo();
2806
2807 /* init platform op table related */
2808 __init_platform_opt(ddr_mode);
2809
2810 /* init volt req info, FIXME: pass profile */
2811#if 0
2812 int iprofile = get_profile();
2813#else
2814 get_profile();
2815#endif
2816 __init_volts_info(0);
2817
2818 /* init cpu/ddr/axi related setting */
2819 __init_cpu_opt();
2820 __init_ddr_axi_opt();
2821
2822 /* init freq-chg related hw setting */
2823 __init_fc_setting();
2824
2825 cur_cpu_op = &helan2_cpu_bootop;
2826 cur_ddr_op = &helan2_ddr_bootop;
2827 cur_axi_op = &helan2_axi_bootop;
2828}
2829
2830void show_op(void)
2831{
2832 struct cpu_opt cop, *op;
2833 struct ddr_opt ddr_op, *ddr_opt;
2834 struct axi_opt axi_op, *axi_opt;
2835 unsigned int ddr_opt_size, axi_opt_size, i;
2836
2837 ddr_opt = cur_platform_opt->ddr_opt;
2838 ddr_opt_size = cur_platform_opt->ddr_opt_size;
2839 axi_opt = cur_platform_opt->axi_opt;
2840 axi_opt_size = cur_platform_opt->axi_opt_size;
2841
2842 printf("Current OP:\n");
2843 memcpy(&cop, cur_cpu_op, sizeof(struct cpu_opt));
2844 printf("pclk(src:sel) l2clk(src)\tpdclk(src)\tbaclk(src)\tperiphclk(src)\n");
2845 printf("%d(%d:%d)\t%d([%s])\t%d([%s])\t%d([%s])\t%d([%s])\n",
2846 cop.pclk, cop.ap_clk_src,
2847 cop.ap_clk_sel & AP_SRC_SEL_MASK,
2848 cop.l2clk, cop.l2clk ? "pclk" : "NULL",
2849 cop.pdclk, cop.l2clk ? "l2clk" : "pclk",
2850 cop.baclk, cop.l2clk ? "l2clk" : "pclk",
2851 cop.periphclk, cop.periphclk ? "pclk" : "NULL");
2852
2853 memcpy(&ddr_op, cur_ddr_op, sizeof(struct ddr_opt));
2854 printf("dclk(src:sel)\n");
2855 printf("%d(%d:%d)\n", ddr_op.dclk, ddr_op.ddr_clk_src,
2856 ddr_op.ddr_clk_sel);
2857
2858 memcpy(&axi_op, cur_axi_op, sizeof(struct axi_opt));
2859 printf("aclk(src:sel)\n");
2860 printf("%d(%d:%d)\n",
2861 axi_op.aclk, axi_op.axi_clk_src, axi_op.axi_clk_sel);
2862
2863 printf("\nAll supported OP:\n");
2864 printf("Core(MHZ@mV):\n");
2865 list_for_each_entry(op, &core_op_list, node)
2866 printf("%d@%d\t", op->pclk, op->volts);
2867
2868 printf("\n");
2869
2870 printf("DDR(MHZ@mV):\n");
2871 for (i = 0; i < ddr_opt_size; i++)
2872 printf("%d@%d\t", ddr_opt[i].dclk, ddr_opt[i].volts);
2873 printf("\n");
2874
2875 printf("AXI(MHZ@mV):\n");
2876 for (i = 0; i < axi_opt_size; i++)
2877 printf("%d@%d\t", axi_opt[i].aclk, axi_opt[i].volts);
2878 printf("\n");
2879}
2880
2881int do_op(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2882{
2883 unsigned int pclk, dclk, aclk;
2884
2885 if (argc == 4) {
2886 pclk = simple_strtoul(argv[1], NULL, 0);
2887 dclk = simple_strtoul(argv[2], NULL, 0);
2888 aclk = simple_strtoul(argv[3], NULL, 0);
2889 printf("op: pclk = %dMHZ dclk = %dMHZ aclk = %dMHZ\n",
2890 pclk, dclk, aclk);
2891
2892 setop(pclk, dclk, aclk);
2893 } else if (argc >= 2) {
2894 printf("usage: op pclk dclk aclk(unit Mhz)\n");
2895 } else {
2896 show_op();
2897 }
2898 return 0;
2899}
2900
2901U_BOOT_CMD(
2902 op, 4, 1, do_op,
2903 "change operating point",
2904 "[ op number ]"
2905);
2906
2907#define PM812_SLAVE_ADDR 0x31
2908#define PM812_VBUCK1_SET0_REG 0x3c /* dvc[1:0] = 0x0 */
2909
2910#define VOL_BASE 600000
2911#define VOL_STEP 12500
2912#define VOL_HIGH 1400000
2913
2914#define PM812_DVC1 93
2915#define PM812_DVC2 94
2916
2917static int set_volt(u32 vol)
2918{
2919 int ret = 0;
2920 struct pmic *p_power;
2921
2922 vol *= 1000;
2923 if ((vol < VOL_BASE) || (vol > VOL_HIGH)) {
2924 printf("out of range when set voltage!\n");
2925 return -1;
2926 }
2927
2928 p_power = pmic_get(MARVELL_PMIC_POWER);
2929 if (!p_power)
2930 return -1;
2931 if (pmic_probe(p_power))
2932 return -1;
2933 ret = marvell88pm_set_buck_vol(p_power, 1, vol);
2934 printf("Set VBUCK1 to %4dmV\n", vol / 1000);
2935
2936 /* always use DVC[1:0] = 0 in uboot */
2937 /* TODO : make sure DVC pins' function is GPIO */
2938 gpio_direction_output(PM812_DVC1, 0);
2939 gpio_direction_output(PM812_DVC2, 0);
2940 return ret;
2941}
2942
2943static u32 get_volt(void)
2944{
2945 u32 vol = 0;
2946 struct pmic *p_power;
2947
2948 p_power = pmic_get(MARVELL_PMIC_POWER);
2949 if (!p_power)
2950 return -1;
2951 if (pmic_probe(p_power))
2952 return -1;
2953
2954 vol = marvell88pm_get_buck_vol(p_power, 1);
2955 if (vol < 0)
2956 return -1;
2957
2958 return vol / 1000;
2959}
2960
2961int do_setvolt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
2962{
2963 ulong vol;
2964 int res = -1;
2965 if ((argc < 1) || (argc > 2))
2966 return -1;
2967
2968 if (argc == 1) {
2969 printf("usage: setvolt xxxx(unit mV)\n"
2970 "xxxx can be 600mV~1350mV, step 13mV\n"
2971 );
2972 return 0;
2973 }
2974 res = strict_strtoul(argv[1], 0, &vol);
2975 if (res == 0 && set_volt(vol) == 0)
2976 printf("Voltage change was successful\n");
2977 else
2978 printf("Voltage change was unsuccessful\n");
2979
2980 return 0;
2981}
2982
2983U_BOOT_CMD(
2984 setvolt, 6, 1, do_setvolt,
2985 "Setting voltages",
2986 ""
2987);
2988
2989int do_pllops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
2990{
2991 ulong pllx, enable, vco = 0, pll = 0, pllp = 0;
2992 int res = -1;
2993
2994 if (argc != 6) {
2995 printf("usage:\n");
2996 printf("pll 2/3 1 pll2/3vcofreq pll2/3freq pll2p/3pfreq");
2997 printf(" enable pll2/3 and set to XXX MHZ\n");
2998 printf("pll 2/3 1 0 0 0 enable pll2/3 at default frequency\n");
2999 printf("pll 2/3 0 0 0 0 disable pll2/3\n");
3000 return -1;
3001 }
3002
3003 res = strict_strtoul(argv[1], 0, &pllx);
3004 if (res < 0) {
3005 printf("Failed to get pll num\n");
3006 return -res;
3007 }
3008
3009 res = strict_strtoul(argv[2], 0, &enable);
3010 if (res < 0) {
3011 printf("Failed to get enable/disable flag\n");
3012 return -res;
3013 }
3014
3015 res = strict_strtoul(argv[3], 0, &vco);
3016 if (res < 0) {
3017 printf("Failed to get enable/disable flag\n");
3018 return -res;
3019 }
3020
3021 res = strict_strtoul(argv[4], 0, &pll);
3022 if (res < 0) {
3023 printf("Failed to get enable/disable flag\n");
3024 return -res;
3025 }
3026
3027 res = strict_strtoul(argv[5], 0, &pllp);
3028 if (res < 0) {
3029 printf("Failed to get enable/disable flag\n");
3030 return -res;
3031 }
3032
3033 if (enable) {
3034 if (vco)
3035 set_pll_freq(pllx, vco, pll, pllp);
3036 else
3037 turn_on_pll(pllx);
3038 } else {
3039 turn_off_pll(pllx);
3040 }
3041 return 0;
3042}
3043
3044U_BOOT_CMD(
3045 pllops, 6, 1, do_pllops,
3046 "Set PLL2/3 output",
3047 ""
3048);
3049
3050int do_setcpurate(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3051{
3052 struct cpu_opt *cop;
3053 ulong freq;
3054 int res = -1;
3055
3056 if (argc != 2) {
3057 printf("usage: set core frequency xxxx(unit Mhz)\n");
3058 printf("Supported Core frequency: ");
3059 list_for_each_entry(cop, &core_op_list, node)
3060 printf("%d\t", cop->pclk);
3061 printf("\n");
3062 return res;
3063 }
3064 res = strict_strtoul(argv[1], 0, &freq);
3065 if ((res == 0) && (cpu_setrate(freq) == 0))
3066 printf("Core freq change was successful\n");
3067 else
3068 printf("Core freq change was unsuccessful\n");
3069 return 0;
3070}
3071
3072U_BOOT_CMD(
3073 setcpurate, 6, 1, do_setcpurate,
3074 "Setting core rate",
3075 ""
3076);
3077
3078int do_setddrrate(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3079{
3080 struct ddr_opt *ddr_opt;
3081 unsigned int ddr_opt_size = 0, i;
3082 ulong freq;
3083 int res = -1;
3084
3085 ddr_opt = cur_platform_opt->ddr_opt;
3086 ddr_opt_size = cur_platform_opt->ddr_opt_size;
3087
3088 if (argc != 2) {
3089 printf("usage: set ddr frequency xxxx(unit Mhz)\n");
3090 printf("Supported ddr frequency: ");
3091 for (i = 0; i < ddr_opt_size; i++)
3092 printf("%d\t", ddr_opt[i].dclk);
3093
3094 printf("\n");
3095 return -1;
3096 }
3097
3098 res = strict_strtoul(argv[1], 0, &freq);
3099 if ((res == 0) && (ddr_setrate(freq) == 0))
3100 printf("DDR freq change was successful\n");
3101 else
3102 printf("DDR freq change was unsuccessful\n");
3103
3104 return 0;
3105}
3106
3107U_BOOT_CMD(
3108 setddrrate, 6, 1, do_setddrrate,
3109 "Setting ddr rate",
3110 ""
3111);
3112
3113int do_setaxirate(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3114{
3115 struct axi_opt *axi_opt;
3116 unsigned int axi_opt_size = 0, i;
3117 ulong freq;
3118 int res = -1;
3119
3120 axi_opt = cur_platform_opt->axi_opt;
3121 axi_opt_size = cur_platform_opt->axi_opt_size;
3122
3123 if (argc != 2) {
3124 printf("usage: set axi frequency xxxx(unit Mhz)\n");
3125 printf("Supported axi frequency: ");
3126 for (i = 0; i < axi_opt_size; i++)
3127 printf("%d\t", axi_opt[i].aclk);
3128
3129 printf("\n");
3130 return -1;
3131 }
3132
3133 res = strict_strtoul(argv[1], 0, &freq);
3134 if ((res == 0) && (axi_setrate(freq) == 0))
3135 printf("AXI freq change was successful\n");
3136 else
3137 printf("AXI freq change was unsuccessful\n");
3138
3139 return 0;
3140}
3141
3142U_BOOT_CMD(
3143 setaxirate, 6, 1, do_setaxirate,
3144 "Setting axi rate",
3145 ""
3146);