1
2
3
4
5
6
7
8
9#include <common.h>
10#include <clock_legacy.h>
11#include <cpu_func.h>
12#include <linux/compiler.h>
13#include <fsl_ifc.h>
14#include <asm/processor.h>
15#include <asm/io.h>
16#include <asm/arch-fsl-layerscape/immap_lsch3.h>
17#include <asm/arch/clock.h>
18#include <asm/arch/soc.h>
19#include "cpu.h"
20
21DECLARE_GLOBAL_DATA_PTR;
22
23#ifndef CONFIG_SYS_FSL_NUM_CC_PLLS
24#define CONFIG_SYS_FSL_NUM_CC_PLLS 6
25#endif
26
27
28void get_sys_info(struct sys_info *sys_info)
29{
30 struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
31 struct ccsr_clk_cluster_group __iomem *clk_grp[2] = {
32 (void *)(CONFIG_SYS_FSL_CH3_CLK_GRPA_ADDR),
33 (void *)(CONFIG_SYS_FSL_CH3_CLK_GRPB_ADDR)
34 };
35 struct ccsr_clk_ctrl __iomem *clk_ctrl =
36 (void *)(CONFIG_SYS_FSL_CH3_CLK_CTRL_ADDR);
37 unsigned int cpu;
38 const u8 core_cplx_pll[16] = {
39 [0] = 0,
40 [1] = 0,
41 [2] = 0,
42 [4] = 1,
43 [5] = 1,
44 [6] = 1,
45 [8] = 2,
46 [9] = 2,
47 [10] = 2,
48 [12] = 3,
49 [13] = 3,
50 [14] = 3,
51 };
52
53 const u8 core_cplx_pll_div[16] = {
54 [0] = 1,
55 [1] = 2,
56 [2] = 4,
57 [4] = 1,
58 [5] = 2,
59 [6] = 4,
60 [8] = 1,
61 [9] = 2,
62 [10] = 4,
63 [12] = 1,
64 [13] = 2,
65 [14] = 4,
66 };
67
68 uint i, cluster;
69#if defined(CONFIG_ARCH_LS1028A) || defined(CONFIG_ARCH_LS1088A)
70 uint rcw_tmp;
71#endif
72 uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS];
73 uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS];
74 unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
75 int cc_group[12] = CONFIG_SYS_FSL_CLUSTER_CLOCKS;
76 u32 c_pll_sel, cplx_pll;
77 void *offset;
78
79 sys_info->freq_systembus = sysclk;
80#ifdef CONFIG_DDR_CLK_FREQ
81 sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ;
82#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
83 sys_info->freq_ddrbus2 = CONFIG_DDR_CLK_FREQ;
84#endif
85#else
86 sys_info->freq_ddrbus = sysclk;
87#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
88 sys_info->freq_ddrbus2 = sysclk;
89#endif
90#endif
91
92
93 sys_info->freq_systembus *= (gur_in32(&gur->rcwsr[0]) >>
94 FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_SHIFT) &
95 FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_MASK;
96 sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >>
97 FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_SHIFT) &
98 FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_MASK;
99#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
100 if (soc_has_dp_ddr()) {
101 sys_info->freq_ddrbus2 *= (gur_in32(&gur->rcwsr[0]) >>
102 FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_SHIFT) &
103 FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_MASK;
104 } else {
105 sys_info->freq_ddrbus2 = 0;
106 }
107#endif
108
109 for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) {
110
111
112
113
114 offset = (void *)((size_t)clk_grp[i/3] +
115 offsetof(struct ccsr_clk_cluster_group,
116 pllngsr[i%3].gsr));
117 ratio[i] = (in_le32(offset) >> 1) & 0x3f;
118 freq_c_pll[i] = sysclk * ratio[i];
119 }
120
121 for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) {
122 cluster = fsl_qoriq_core_to_cluster(cpu);
123 c_pll_sel = (in_le32(&clk_ctrl->clkcncsr[cluster].csr) >> 27)
124 & 0xf;
125 cplx_pll = core_cplx_pll[c_pll_sel];
126 cplx_pll += cc_group[cluster] - 1;
127 sys_info->freq_processor[cpu] =
128 freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
129 }
130
131#if defined(CONFIG_FSL_IFC)
132 sys_info->freq_localbus = sys_info->freq_systembus /
133 CONFIG_SYS_FSL_IFC_CLK_DIV;
134#endif
135
136#if defined(CONFIG_ARCH_LS1028A) || defined(CONFIG_ARCH_LS1088A)
137#define HWA_CGA_M2_CLK_SEL 0x00380000
138#define HWA_CGA_M2_CLK_SHIFT 19
139 rcw_tmp = in_le32(&gur->rcwsr[5]);
140 switch ((rcw_tmp & HWA_CGA_M2_CLK_SEL) >> HWA_CGA_M2_CLK_SHIFT) {
141 case 1:
142 sys_info->freq_cga_m2 = freq_c_pll[1];
143 break;
144 case 2:
145 sys_info->freq_cga_m2 = freq_c_pll[1] / 2;
146 break;
147 case 3:
148 sys_info->freq_cga_m2 = freq_c_pll[1] / 3;
149 break;
150 case 4:
151 sys_info->freq_cga_m2 = freq_c_pll[1] / 4;
152 break;
153 case 6:
154 sys_info->freq_cga_m2 = freq_c_pll[0] / 2;
155 break;
156 case 7:
157 sys_info->freq_cga_m2 = freq_c_pll[0] / 3;
158 break;
159 default:
160 printf("Error: Unknown peripheral clock select!\n");
161 break;
162 }
163#endif
164}
165
166int get_clocks(void)
167{
168 struct sys_info sys_info;
169#ifdef CONFIG_FSL_ESDHC
170 u32 clock = 0;
171#endif
172 get_sys_info(&sys_info);
173 gd->cpu_clk = sys_info.freq_processor[0];
174 gd->bus_clk = sys_info.freq_systembus / CONFIG_SYS_FSL_PCLK_DIV;
175 gd->mem_clk = sys_info.freq_ddrbus;
176#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
177 gd->arch.mem2_clk = sys_info.freq_ddrbus2;
178#endif
179
180#ifdef CONFIG_FSL_ESDHC
181#if defined(CONFIG_ARCH_LS1028A) || defined(CONFIG_ARCH_LS1088A)
182 clock = sys_info.freq_cga_m2;
183#elif defined(CONFIG_ARCH_LX2160A) || defined(CONFIG_ARCH_LS2080A)
184 clock = sys_info.freq_systembus;
185#endif
186 gd->arch.sdhc_per_clk = clock / CONFIG_SYS_FSL_SDHC_CLK_DIV;
187 gd->arch.sdhc_clk = gd->bus_clk / CONFIG_SYS_FSL_SDHC_CLK_DIV;
188#endif
189
190 if (gd->cpu_clk != 0)
191 return 0;
192 else
193 return 1;
194}
195
196
197
198
199
200ulong get_bus_freq(ulong dummy)
201{
202 if (!gd->bus_clk)
203 get_clocks();
204
205 return gd->bus_clk;
206}
207
208
209
210
211
212ulong get_ddr_freq(ulong ctrl_num)
213{
214 if (!gd->mem_clk)
215 get_clocks();
216
217
218
219
220
221#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
222 if (ctrl_num >= 2)
223 return gd->arch.mem2_clk;
224#endif
225
226 return gd->mem_clk;
227}
228
229int get_i2c_freq(ulong dummy)
230{
231 return get_bus_freq(0) / CONFIG_SYS_FSL_I2C_CLK_DIV;
232}
233
234int get_dspi_freq(ulong dummy)
235{
236 return get_bus_freq(0) / CONFIG_SYS_FSL_DSPI_CLK_DIV;
237}
238
239int get_serial_clock(void)
240{
241 return get_bus_freq(0) / CONFIG_SYS_FSL_DUART_CLK_DIV;
242}
243
244unsigned int mxc_get_clock(enum mxc_clock clk)
245{
246 switch (clk) {
247 case MXC_I2C_CLK:
248 return get_i2c_freq(0);
249 case MXC_DSPI_CLK:
250 return get_dspi_freq(0);
251 default:
252 printf("Unsupported clock\n");
253 }
254 return 0;
255}
256