1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright 2015 Freescale Semiconductor, Inc.
4 * Copyright 2019 NXP.
5 */
6
7 #include <common.h>
8 #include <cpu_func.h>
9 #include <linux/compiler.h>
10 #include <asm/io.h>
11 #include <asm/processor.h>
12 #include <asm/arch/clock.h>
13 #include <asm/arch/soc.h>
14 #include <fsl_ifc.h>
15 #include "cpu.h"
16
17 DECLARE_GLOBAL_DATA_PTR;
18
19 #ifndef CONFIG_SYS_FSL_NUM_CC_PLLS
20 #define CONFIG_SYS_FSL_NUM_CC_PLLS 2
21 #endif
22
get_sys_info(struct sys_info * sys_info)23 void get_sys_info(struct sys_info *sys_info)
24 {
25 struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
26 /* rcw_tmp is needed to get FMAN clock, or to get cluster group A
27 * mux 2 clock for LS1043A/LS1046A.
28 */
29 #if defined(CONFIG_SYS_DPAA_FMAN) || \
30 defined(CONFIG_TARGET_LS1046ARDB) || \
31 defined(CONFIG_TARGET_LS1043ARDB)
32 u32 rcw_tmp;
33 #endif
34 struct ccsr_clk *clk = (void *)(CONFIG_SYS_FSL_CLK_ADDR);
35 unsigned int cpu;
36 const u8 core_cplx_pll[8] = {
37 [0] = 0, /* CC1 PPL / 1 */
38 [1] = 0, /* CC1 PPL / 2 */
39 [4] = 1, /* CC2 PPL / 1 */
40 [5] = 1, /* CC2 PPL / 2 */
41 };
42
43 const u8 core_cplx_pll_div[8] = {
44 [0] = 1, /* CC1 PPL / 1 */
45 [1] = 2, /* CC1 PPL / 2 */
46 [4] = 1, /* CC2 PPL / 1 */
47 [5] = 2, /* CC2 PPL / 2 */
48 };
49
50 uint i, cluster;
51 uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS];
52 uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS];
53 unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
54 unsigned long cluster_clk;
55
56 sys_info->freq_systembus = sysclk;
57 #ifndef CONFIG_CLUSTER_CLK_FREQ
58 #define CONFIG_CLUSTER_CLK_FREQ CONFIG_SYS_CLK_FREQ
59 #endif
60 cluster_clk = CONFIG_CLUSTER_CLK_FREQ;
61
62 #ifdef CONFIG_DDR_CLK_FREQ
63 sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ;
64 #else
65 sys_info->freq_ddrbus = sysclk;
66 #endif
67
68 /* The freq_systembus is used to record frequency of platform PLL */
69 sys_info->freq_systembus *= (gur_in32(&gur->rcwsr[0]) >>
70 FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_SHIFT) &
71 FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_MASK;
72
73 #ifdef CONFIG_ARCH_LS1012A
74 sys_info->freq_ddrbus = 2 * sys_info->freq_systembus;
75 #else
76 sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >>
77 FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_SHIFT) &
78 FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_MASK;
79 #endif
80
81 for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) {
82 ratio[i] = (in_be32(&clk->pllcgsr[i].pllcngsr) >> 1) & 0xff;
83 if (ratio[i] > 4)
84 freq_c_pll[i] = cluster_clk * ratio[i];
85 else
86 freq_c_pll[i] = sys_info->freq_systembus * ratio[i];
87 }
88
89 for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) {
90 cluster = fsl_qoriq_core_to_cluster(cpu);
91 u32 c_pll_sel = (in_be32(&clk->clkcsr[cluster].clkcncsr) >> 27)
92 & 0xf;
93 u32 cplx_pll = core_cplx_pll[c_pll_sel];
94
95 sys_info->freq_processor[cpu] =
96 freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
97 }
98
99 #define HWA_CGA_M1_CLK_SEL 0xe0000000
100 #define HWA_CGA_M1_CLK_SHIFT 29
101 #ifdef CONFIG_SYS_DPAA_FMAN
102 rcw_tmp = in_be32(&gur->rcwsr[7]);
103 switch ((rcw_tmp & HWA_CGA_M1_CLK_SEL) >> HWA_CGA_M1_CLK_SHIFT) {
104 case 2:
105 sys_info->freq_fman[0] = freq_c_pll[0] / 2;
106 break;
107 case 3:
108 sys_info->freq_fman[0] = freq_c_pll[0] / 3;
109 break;
110 case 4:
111 sys_info->freq_fman[0] = freq_c_pll[0] / 4;
112 break;
113 case 5:
114 sys_info->freq_fman[0] = sys_info->freq_systembus;
115 break;
116 case 6:
117 sys_info->freq_fman[0] = freq_c_pll[1] / 2;
118 break;
119 case 7:
120 sys_info->freq_fman[0] = freq_c_pll[1] / 3;
121 break;
122 default:
123 printf("Error: Unknown FMan1 clock select!\n");
124 break;
125 }
126 #endif
127
128 #ifdef CONFIG_FSL_ESDHC
129 #define HWA_CGA_M2_CLK_SEL 0x00000007
130 #define HWA_CGA_M2_CLK_SHIFT 0
131 #if defined(CONFIG_TARGET_LS1046ARDB) || defined(CONFIG_TARGET_LS1043ARDB)
132 rcw_tmp = in_be32(&gur->rcwsr[15]);
133 switch ((rcw_tmp & HWA_CGA_M2_CLK_SEL) >> HWA_CGA_M2_CLK_SHIFT) {
134 case 1:
135 sys_info->freq_cga_m2 = freq_c_pll[1];
136 break;
137 #if defined(CONFIG_TARGET_LS1046ARDB)
138 case 2:
139 sys_info->freq_cga_m2 = freq_c_pll[1] / 2;
140 break;
141 #endif
142 case 3:
143 sys_info->freq_cga_m2 = freq_c_pll[1] / 3;
144 break;
145 #if defined(CONFIG_TARGET_LS1046ARDB)
146 case 6:
147 sys_info->freq_cga_m2 = freq_c_pll[0] / 2;
148 break;
149 #endif
150 default:
151 printf("Error: Unknown peripheral clock select!\n");
152 break;
153 }
154 #endif
155 #endif
156
157 #if defined(CONFIG_FSL_IFC)
158 sys_info->freq_localbus = sys_info->freq_systembus /
159 CONFIG_SYS_FSL_IFC_CLK_DIV;
160 #endif
161 #ifdef CONFIG_SYS_DPAA_QBMAN
162 sys_info->freq_qman = (sys_info->freq_systembus /
163 CONFIG_SYS_FSL_PCLK_DIV) /
164 CONFIG_SYS_FSL_QMAN_CLK_DIV;
165 #endif
166 }
167
168 #ifdef CONFIG_SYS_DPAA_QBMAN
get_qman_freq(void)169 unsigned long get_qman_freq(void)
170 {
171 struct sys_info sys_info;
172
173 get_sys_info(&sys_info);
174
175 return sys_info.freq_qman;
176 }
177 #endif
178
get_clocks(void)179 int get_clocks(void)
180 {
181 struct sys_info sys_info;
182
183 get_sys_info(&sys_info);
184 gd->cpu_clk = sys_info.freq_processor[0];
185 gd->bus_clk = sys_info.freq_systembus / CONFIG_SYS_FSL_PCLK_DIV;
186 gd->mem_clk = sys_info.freq_ddrbus;
187
188 #ifdef CONFIG_FSL_ESDHC
189 #if defined(CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK)
190 #if defined(CONFIG_TARGET_LS1046ARDB)
191 gd->arch.sdhc_clk = sys_info.freq_cga_m2 / 2;
192 #endif
193 #if defined(CONFIG_TARGET_LS1043ARDB)
194 gd->arch.sdhc_clk = sys_info.freq_cga_m2;
195 #endif
196 #if defined(CONFIG_TARGET_LS1012ARDB)
197 gd->arch.sdhc_clk = sys_info.freq_systembus;
198 #endif
199 #else
200 gd->arch.sdhc_clk = (sys_info.freq_systembus /
201 CONFIG_SYS_FSL_PCLK_DIV) /
202 CONFIG_SYS_FSL_SDHC_CLK_DIV;
203 #endif
204 #endif
205 if (gd->cpu_clk != 0)
206 return 0;
207 else
208 return 1;
209 }
210
211 /********************************************
212 * get_bus_freq
213 * return platform clock in Hz
214 *********************************************/
get_bus_freq(ulong dummy)215 ulong get_bus_freq(ulong dummy)
216 {
217 if (!gd->bus_clk)
218 get_clocks();
219
220 return gd->bus_clk;
221 }
222
get_ddr_freq(ulong dummy)223 ulong get_ddr_freq(ulong dummy)
224 {
225 if (!gd->mem_clk)
226 get_clocks();
227
228 return gd->mem_clk;
229 }
230
get_serial_clock(void)231 int get_serial_clock(void)
232 {
233 return get_bus_freq(0) / CONFIG_SYS_FSL_DUART_CLK_DIV;
234 }
235
get_i2c_freq(ulong dummy)236 int get_i2c_freq(ulong dummy)
237 {
238 return get_bus_freq(0) / CONFIG_SYS_FSL_I2C_CLK_DIV;
239 }
240
get_dspi_freq(ulong dummy)241 int get_dspi_freq(ulong dummy)
242 {
243 return get_bus_freq(0) / CONFIG_SYS_FSL_DSPI_CLK_DIV;
244 }
245
246 #ifdef CONFIG_FSL_LPUART
get_uart_freq(ulong dummy)247 int get_uart_freq(ulong dummy)
248 {
249 return get_bus_freq(0) / CONFIG_SYS_FSL_LPUART_CLK_DIV;
250 }
251 #endif
252
mxc_get_clock(enum mxc_clock clk)253 unsigned int mxc_get_clock(enum mxc_clock clk)
254 {
255 switch (clk) {
256 case MXC_I2C_CLK:
257 return get_i2c_freq(0);
258 case MXC_DSPI_CLK:
259 return get_dspi_freq(0);
260 #ifdef CONFIG_FSL_LPUART
261 case MXC_UART_CLK:
262 return get_uart_freq(0);
263 #endif
264 default:
265 printf("Unsupported clock\n");
266 }
267 return 0;
268 }
269