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