xref: /arm-trusted-firmware/plat/imx/imx8m/ddr/clock.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright 2018-2023 NXP
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <stdbool.h>
8*91f16700Schasinglulu 
9*91f16700Schasinglulu #include <lib/mmio.h>
10*91f16700Schasinglulu #include <platform_def.h>
11*91f16700Schasinglulu 
12*91f16700Schasinglulu #define IMX_CCM_IP_BASE				(IMX_CCM_BASE + 0xa000)
13*91f16700Schasinglulu #define DRAM_SEL_CFG				(IMX_CCM_BASE + 0x9800)
14*91f16700Schasinglulu #define CCM_IP_CLK_ROOT_GEN_TAGET(i)		(IMX_CCM_IP_BASE + 0x80 * (i) + 0x00)
15*91f16700Schasinglulu #define CCM_IP_CLK_ROOT_GEN_TAGET_SET(i)	(IMX_CCM_IP_BASE + 0x80 * (i) + 0x04)
16*91f16700Schasinglulu #define CCM_IP_CLK_ROOT_GEN_TAGET_CLR(i)	(IMX_CCM_IP_BASE + 0x80 * (i) + 0x08)
17*91f16700Schasinglulu #define PLL_FREQ_800M	U(0x00ece580)
18*91f16700Schasinglulu #define PLL_FREQ_400M	U(0x00ec6984)
19*91f16700Schasinglulu #define PLL_FREQ_167M	U(0x00f5a406)
20*91f16700Schasinglulu 
21*91f16700Schasinglulu void ddr_pll_bypass_100mts(void)
22*91f16700Schasinglulu {
23*91f16700Schasinglulu 	/* change the clock source of dram_alt_clk_root to source 2 --100MHz */
24*91f16700Schasinglulu 	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(0), (0x7 << 24) | (0x7 << 16));
25*91f16700Schasinglulu 	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(0), (0x2 << 24));
26*91f16700Schasinglulu 
27*91f16700Schasinglulu 	/* change the clock source of dram_apb_clk_root to source 2 --40MHz/2 */
28*91f16700Schasinglulu 	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(1), (0x7 << 24) | (0x7 << 16));
29*91f16700Schasinglulu 	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(1), (0x2 << 24) | (0x1 << 16));
30*91f16700Schasinglulu 
31*91f16700Schasinglulu 	/* configure pll bypass mode */
32*91f16700Schasinglulu 	mmio_write_32(DRAM_SEL_CFG + 0x4, BIT(24));
33*91f16700Schasinglulu }
34*91f16700Schasinglulu 
35*91f16700Schasinglulu void ddr_pll_bypass_400mts(void)
36*91f16700Schasinglulu {
37*91f16700Schasinglulu 	/* change the clock source of dram_alt_clk_root to source 1 --400MHz */
38*91f16700Schasinglulu 	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(0), (0x7 << 24) | (0x7 << 16));
39*91f16700Schasinglulu 	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(0), (0x1 << 24) | (0x1 << 16));
40*91f16700Schasinglulu 
41*91f16700Schasinglulu 	/* change the clock source of dram_apb_clk_root to source 3 --160MHz/2 */
42*91f16700Schasinglulu 	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(1), (0x7 << 24) | (0x7 << 16));
43*91f16700Schasinglulu 	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(1), (0x3 << 24) | (0x1 << 16));
44*91f16700Schasinglulu 
45*91f16700Schasinglulu 	/* configure pll bypass mode */
46*91f16700Schasinglulu 	mmio_write_32(DRAM_SEL_CFG + 0x4, BIT(24));
47*91f16700Schasinglulu }
48*91f16700Schasinglulu 
49*91f16700Schasinglulu void ddr_pll_unbypass(void)
50*91f16700Schasinglulu {
51*91f16700Schasinglulu 	mmio_write_32(DRAM_SEL_CFG + 0x8, BIT(24));
52*91f16700Schasinglulu 	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(1), (0x7 << 24) | (0x7 << 16));
53*91f16700Schasinglulu 	/* to source 4 --800MHz/5 */
54*91f16700Schasinglulu 	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(1), (0x4 << 24) | (0x4 << 16));
55*91f16700Schasinglulu }
56*91f16700Schasinglulu 
57*91f16700Schasinglulu #if defined(PLAT_imx8mq)
58*91f16700Schasinglulu void dram_pll_init(unsigned int drate)
59*91f16700Schasinglulu {
60*91f16700Schasinglulu 	/* bypass the PLL */
61*91f16700Schasinglulu 	mmio_setbits_32(HW_DRAM_PLL_CFG0, 0x30);
62*91f16700Schasinglulu 
63*91f16700Schasinglulu 	switch (drate) {
64*91f16700Schasinglulu 	case 3200:
65*91f16700Schasinglulu 		mmio_write_32(HW_DRAM_PLL_CFG2, PLL_FREQ_800M);
66*91f16700Schasinglulu 		break;
67*91f16700Schasinglulu 	case 1600:
68*91f16700Schasinglulu 		mmio_write_32(HW_DRAM_PLL_CFG2, PLL_FREQ_400M);
69*91f16700Schasinglulu 		break;
70*91f16700Schasinglulu 	case 667:
71*91f16700Schasinglulu 		mmio_write_32(HW_DRAM_PLL_CFG2, PLL_FREQ_167M);
72*91f16700Schasinglulu 		break;
73*91f16700Schasinglulu 	default:
74*91f16700Schasinglulu 		break;
75*91f16700Schasinglulu 	}
76*91f16700Schasinglulu 
77*91f16700Schasinglulu 	/* unbypass the PLL */
78*91f16700Schasinglulu 	mmio_clrbits_32(HW_DRAM_PLL_CFG0, 0x30);
79*91f16700Schasinglulu 	while (!(mmio_read_32(HW_DRAM_PLL_CFG0) & BIT(31))) {
80*91f16700Schasinglulu 		;
81*91f16700Schasinglulu 	}
82*91f16700Schasinglulu }
83*91f16700Schasinglulu #else
84*91f16700Schasinglulu void dram_pll_init(unsigned int drate)
85*91f16700Schasinglulu {
86*91f16700Schasinglulu 	/* bypass the PLL */
87*91f16700Schasinglulu 	mmio_setbits_32(DRAM_PLL_CTRL, (1 << 16));
88*91f16700Schasinglulu 	mmio_clrbits_32(DRAM_PLL_CTRL, (1 << 9));
89*91f16700Schasinglulu 
90*91f16700Schasinglulu 	switch (drate) {
91*91f16700Schasinglulu 	case 4000:
92*91f16700Schasinglulu 		mmio_write_32(DRAM_PLL_CTRL + 0x4, (250 << 12) | (3 << 4) | 1);
93*91f16700Schasinglulu 		break;
94*91f16700Schasinglulu 	case 3733:
95*91f16700Schasinglulu 	case 3732:
96*91f16700Schasinglulu 		mmio_write_32(DRAM_PLL_CTRL + 0x4, (311 << 12) | (4 << 4) | 1);
97*91f16700Schasinglulu 		break;
98*91f16700Schasinglulu 	case 3200:
99*91f16700Schasinglulu 		mmio_write_32(DRAM_PLL_CTRL + 0x4, (200 << 12) | (3 << 4) | 1);
100*91f16700Schasinglulu 		break;
101*91f16700Schasinglulu 	case 2400:
102*91f16700Schasinglulu 		mmio_write_32(DRAM_PLL_CTRL + 0x4, (300 << 12) | (3 << 4) | 2);
103*91f16700Schasinglulu 		break;
104*91f16700Schasinglulu 	case 1600:
105*91f16700Schasinglulu 		mmio_write_32(DRAM_PLL_CTRL + 0x4, (400 << 12) | (3 << 4) | 3);
106*91f16700Schasinglulu 		break;
107*91f16700Schasinglulu 	case 1066:
108*91f16700Schasinglulu 		mmio_write_32(DRAM_PLL_CTRL + 0x4, (266 << 12) | (3 << 4) | 3);
109*91f16700Schasinglulu 		break;
110*91f16700Schasinglulu 	case 667:
111*91f16700Schasinglulu 		mmio_write_32(DRAM_PLL_CTRL + 0x4, (334 << 12) | (3 << 4) | 4);
112*91f16700Schasinglulu 		break;
113*91f16700Schasinglulu 	default:
114*91f16700Schasinglulu 		break;
115*91f16700Schasinglulu 	}
116*91f16700Schasinglulu 
117*91f16700Schasinglulu 	mmio_setbits_32(DRAM_PLL_CTRL, BIT(9));
118*91f16700Schasinglulu 	/* wait for PLL locked */
119*91f16700Schasinglulu 	while (!(mmio_read_32(DRAM_PLL_CTRL) & BIT(31))) {
120*91f16700Schasinglulu 		;
121*91f16700Schasinglulu 	}
122*91f16700Schasinglulu 
123*91f16700Schasinglulu 	/* unbypass the PLL */
124*91f16700Schasinglulu 	mmio_clrbits_32(DRAM_PLL_CTRL, BIT(16));
125*91f16700Schasinglulu }
126*91f16700Schasinglulu #endif
127*91f16700Schasinglulu 
128*91f16700Schasinglulu /* change the dram clock frequency */
129*91f16700Schasinglulu void dram_clock_switch(unsigned int target_drate, bool bypass_mode)
130*91f16700Schasinglulu {
131*91f16700Schasinglulu 	if (bypass_mode) {
132*91f16700Schasinglulu 		switch (target_drate) {
133*91f16700Schasinglulu 		case 400:
134*91f16700Schasinglulu 			ddr_pll_bypass_400mts();
135*91f16700Schasinglulu 			break;
136*91f16700Schasinglulu 		case 100:
137*91f16700Schasinglulu 			ddr_pll_bypass_100mts();
138*91f16700Schasinglulu 			break;
139*91f16700Schasinglulu 		default:
140*91f16700Schasinglulu 			ddr_pll_unbypass();
141*91f16700Schasinglulu 			break;
142*91f16700Schasinglulu 		}
143*91f16700Schasinglulu 	} else {
144*91f16700Schasinglulu 		dram_pll_init(target_drate);
145*91f16700Schasinglulu 	}
146*91f16700Schasinglulu }
147