1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2015 Freescale Semiconductor, Inc.
7 #include <linux/compiler.h>
9 #include <asm/processor.h>
10 #include <asm/arch/clock.h>
11 #include <asm/arch/soc.h>
15 DECLARE_GLOBAL_DATA_PTR;
17 #ifndef CONFIG_SYS_FSL_NUM_CC_PLLS
18 #define CONFIG_SYS_FSL_NUM_CC_PLLS 2
21 void get_sys_info(struct sys_info *sys_info)
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)
30 struct ccsr_clk *clk = (void *)(CONFIG_SYS_FSL_CLK_ADDR);
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 */
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 */
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;
52 sys_info->freq_systembus = sysclk;
53 #ifndef CONFIG_CLUSTER_CLK_FREQ
54 #define CONFIG_CLUSTER_CLK_FREQ CONFIG_SYS_CLK_FREQ
56 cluster_clk = CONFIG_CLUSTER_CLK_FREQ;
58 #ifdef CONFIG_DDR_CLK_FREQ
59 sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ;
61 sys_info->freq_ddrbus = sysclk;
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;
69 #ifdef CONFIG_ARCH_LS1012A
70 sys_info->freq_ddrbus = 2 * sys_info->freq_systembus;
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;
77 for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) {
78 ratio[i] = (in_be32(&clk->pllcgsr[i].pllcngsr) >> 1) & 0xff;
80 freq_c_pll[i] = cluster_clk * ratio[i];
82 freq_c_pll[i] = sys_info->freq_systembus * ratio[i];
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)
89 u32 cplx_pll = core_cplx_pll[c_pll_sel];
91 sys_info->freq_processor[cpu] =
92 freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
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) {
101 sys_info->freq_fman[0] = freq_c_pll[0] / 2;
104 sys_info->freq_fman[0] = freq_c_pll[0] / 3;
107 sys_info->freq_fman[0] = freq_c_pll[0] / 4;
110 sys_info->freq_fman[0] = sys_info->freq_systembus;
113 sys_info->freq_fman[0] = freq_c_pll[1] / 2;
116 sys_info->freq_fman[0] = freq_c_pll[1] / 3;
119 printf("Error: Unknown FMan1 clock select!\n");
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) {
131 sys_info->freq_sdhc = freq_c_pll[1];
134 sys_info->freq_sdhc = freq_c_pll[1] / 2;
137 sys_info->freq_sdhc = freq_c_pll[1] / 3;
140 sys_info->freq_sdhc = freq_c_pll[0] / 2;
143 printf("Error: Unknown ESDHC clock select!\n");
147 sys_info->freq_sdhc = (sys_info->freq_systembus /
148 CONFIG_SYS_FSL_PCLK_DIV) /
149 CONFIG_SYS_FSL_SDHC_CLK_DIV;
153 #if defined(CONFIG_FSL_IFC)
154 sys_info->freq_localbus = sys_info->freq_systembus /
155 CONFIG_SYS_FSL_IFC_CLK_DIV;
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;
164 #ifdef CONFIG_SYS_DPAA_QBMAN
165 unsigned long get_qman_freq(void)
167 struct sys_info sys_info;
169 get_sys_info(&sys_info);
171 return sys_info.freq_qman;
177 struct sys_info sys_info;
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;
184 #ifdef CONFIG_FSL_ESDHC
185 gd->arch.sdhc_clk = sys_info.freq_sdhc;
188 if (gd->cpu_clk != 0)
194 /********************************************
196 * return platform clock in Hz
197 *********************************************/
198 ulong get_bus_freq(ulong dummy)
206 ulong get_ddr_freq(ulong dummy)
214 #ifdef CONFIG_FSL_ESDHC
215 int get_sdhc_freq(ulong dummy)
217 if (!gd->arch.sdhc_clk)
220 return gd->arch.sdhc_clk;
224 int get_serial_clock(void)
226 return get_bus_freq(0) / CONFIG_SYS_FSL_DUART_CLK_DIV;
229 int get_i2c_freq(ulong dummy)
231 return get_bus_freq(0) / CONFIG_SYS_FSL_I2C_CLK_DIV;
234 int get_dspi_freq(ulong dummy)
236 return get_bus_freq(0) / CONFIG_SYS_FSL_DSPI_CLK_DIV;
239 #ifdef CONFIG_FSL_LPUART
240 int get_uart_freq(ulong dummy)
242 return get_bus_freq(0) / CONFIG_SYS_FSL_LPUART_CLK_DIV;
246 unsigned int mxc_get_clock(enum mxc_clock clk)
250 return get_i2c_freq(0);
251 #if defined(CONFIG_FSL_ESDHC)
253 return get_sdhc_freq(0);
256 return get_dspi_freq(0);
257 #ifdef CONFIG_FSL_LPUART
259 return get_uart_freq(0);
262 printf("Unsupported clock\n");